Skip to content

Commit

Permalink
sdk: add context.Context to REST calls (grafana-tools#77)
Browse files Browse the repository at this point in the history
* sdk: add context.Context to REST calls

Add `context.Context` as the first argument to functions which do
requests. This allows users to have fine-grained control over the
timeouts in the typical Go manner - they will not have to have the same
timeout on all operations that is set via `http.Client`.

This also informs our users that these functions do requests and that
they *do* block for a good reason - a HTTP request is made and then we
block until a response comes.

* rest-request: make it compatible with older versions

Go 1.13 has introduced `NewRequestWithContext()` so for compatibility
reasons let's do it the old way - via `NewRequest()` + `WithContext()`.
  • Loading branch information
GiedriusS authored Mar 26, 2020
1 parent 63c6c7e commit f0431e4
Show file tree
Hide file tree
Showing 24 changed files with 232 additions and 192 deletions.
6 changes: 4 additions & 2 deletions cmd/backup-dashboards/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package main
*/

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand All @@ -44,13 +45,14 @@ func main() {
fmt.Fprint(os.Stderr, "Usage: backup-dashboards http://grafana.host:3000 api-key-string-here\n")
os.Exit(0)
}
ctx := context.Background()
c := sdk.NewClient(os.Args[1], os.Args[2], sdk.DefaultHTTPClient)
if boardLinks, err = c.SearchDashboards("", false); err != nil {
if boardLinks, err = c.SearchDashboards(ctx, "", false); err != nil {
fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", err))
os.Exit(1)
}
for _, link := range boardLinks {
if rawBoard, meta, err = c.GetRawDashboardBySlug(link.URI); err != nil {
if rawBoard, meta, err = c.GetRawDashboardBySlug(ctx, link.URI); err != nil {
fmt.Fprintf(os.Stderr, fmt.Sprintf("%s for %s\n", err, link.URI))
continue
}
Expand Down
4 changes: 3 additions & 1 deletion cmd/backup-datasources/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package main
*/

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand All @@ -46,8 +47,9 @@ func main() {
fmt.Fprint(os.Stderr, "Usage: backup-datasources http://sdk.host:3000 api-key-string-here\n")
os.Exit(0)
}
ctx := context.Background()
c := sdk.NewClient(os.Args[1], os.Args[2], sdk.DefaultHTTPClient)
if datasources, err = c.GetAllDatasources(); err != nil {
if datasources, err = c.GetAllDatasources(ctx); err != nil {
fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", err))
os.Exit(1)
}
Expand Down
4 changes: 3 additions & 1 deletion cmd/import-dashboards-raw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ package main
*/

import (
"context"
"fmt"
"io/ioutil"
"log"
Expand All @@ -50,6 +51,7 @@ func main() {
fmt.Fprint(os.Stderr, "Usage: import-dashboards http://grafana.host:3000 api-key-string-here\n")
os.Exit(0)
}
ctx := context.Background()
c := sdk.NewClient(os.Args[1], os.Args[2], sdk.DefaultHTTPClient)
filesInDir, err = ioutil.ReadDir(".")
if err != nil {
Expand All @@ -61,7 +63,7 @@ func main() {
log.Println(err)
continue
}
_, err := c.SetRawDashboard(rawBoard)
_, err := c.SetRawDashboard(ctx, rawBoard)
if err != nil {
log.Printf("error on importing dashboard from %s", file.Name())
continue
Expand Down
6 changes: 4 additions & 2 deletions cmd/import-dashboards/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package main
*/

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand All @@ -49,6 +50,7 @@ func main() {
fmt.Fprint(os.Stderr, "Usage: import-dashboards http://grafana-host:3000 api-key-string-here\n")
os.Exit(0)
}
ctx := context.Background()
c := sdk.NewClient(os.Args[1], os.Args[2], sdk.DefaultHTTPClient)
filesInDir, err = ioutil.ReadDir(".")
if err != nil {
Expand All @@ -65,12 +67,12 @@ func main() {
log.Println(err)
continue
}
c.DeleteDashboard(board.UpdateSlug())
c.DeleteDashboard(ctx, board.UpdateSlug())
params := sdk.SetDashboardParams{
FolderID: sdk.DefaultFolderId,
Overwrite: false,
}
_, err := c.SetDashboard(board, params)
_, err := c.SetDashboard(ctx, board, params)
if err != nil {
log.Printf("error on importing dashboard %s", board.Title)
continue
Expand Down
8 changes: 5 additions & 3 deletions cmd/import-datasources/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package main
*/

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand All @@ -50,8 +51,9 @@ func main() {
fmt.Fprint(os.Stderr, "Usage: import-datasources http://sdk-host:3000 api-key-string-here\n")
os.Exit(0)
}
ctx := context.Background()
c := sdk.NewClient(os.Args[1], os.Args[2], sdk.DefaultHTTPClient)
if datasources, err = c.GetAllDatasources(); err != nil {
if datasources, err = c.GetAllDatasources(ctx); err != nil {
fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", err))
os.Exit(1)
}
Expand All @@ -72,11 +74,11 @@ func main() {
}
for _, existingDS := range datasources {
if existingDS.Name == newDS.Name {
c.DeleteDatasource(existingDS.ID)
c.DeleteDatasource(ctx, existingDS.ID)
break
}
}
if status, err = c.CreateDatasource(newDS); err != nil {
if status, err = c.CreateDatasource(ctx, newDS); err != nil {
fmt.Fprint(os.Stderr, fmt.Sprintf("error on importing datasource %s with %s (%s)", newDS.Name, err, *status.Message))
}
}
Expand Down
13 changes: 7 additions & 6 deletions rest-admin.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package sdk

import (
"context"
"encoding/json"
"fmt"
)

// CreateUser creates a new global user.
// Requires basic authentication and that the authenticated user is a Grafana Admin.
// Reflects POST /api/admin/users API call.
func (r *Client) CreateUser(user User) (StatusMessage, error) {
func (r *Client) CreateUser(ctx context.Context, user User) (StatusMessage, error) {
var (
raw []byte
resp StatusMessage
Expand All @@ -17,7 +18,7 @@ func (r *Client) CreateUser(user User) (StatusMessage, error) {
if raw, err = json.Marshal(user); err != nil {
return StatusMessage{}, err
}
if raw, _, err = r.post("api/admin/users", nil, raw); err != nil {
if raw, _, err = r.post(ctx, "api/admin/users", nil, raw); err != nil {
return StatusMessage{}, err
}
if err = json.Unmarshal(raw, &resp); err != nil {
Expand All @@ -29,7 +30,7 @@ func (r *Client) CreateUser(user User) (StatusMessage, error) {
// UpdateUserPermissions updates the permissions of a global user.
// Requires basic authentication and that the authenticated user is a Grafana Admin.
// Reflects PUT /api/admin/users/:userId/password API call.
func (r *Client) UpdateUserPermissions(permissions UserPermissions, uid uint) (StatusMessage, error) {
func (r *Client) UpdateUserPermissions(ctx context.Context, permissions UserPermissions, uid uint) (StatusMessage, error) {
var (
raw []byte
reply StatusMessage
Expand All @@ -38,7 +39,7 @@ func (r *Client) UpdateUserPermissions(permissions UserPermissions, uid uint) (S
if raw, err = json.Marshal(permissions); err != nil {
return StatusMessage{}, err
}
if raw, _, err = r.put(fmt.Sprintf("api/admin/users/%d/permissions", uid), nil, raw); err != nil {
if raw, _, err = r.put(ctx, fmt.Sprintf("api/admin/users/%d/permissions", uid), nil, raw); err != nil {
return StatusMessage{}, err
}
err = json.Unmarshal(raw, &reply)
Expand All @@ -48,14 +49,14 @@ func (r *Client) UpdateUserPermissions(permissions UserPermissions, uid uint) (S
// SwitchUserContext switches user context to the given organization.
// Requires basic authentication and that the authenticated user is a Grafana Admin.
// Reflects POST /api/users/:userId/using/:organizationId API call.
func (r *Client) SwitchUserContext(uid uint, oid uint) (StatusMessage, error) {
func (r *Client) SwitchUserContext(ctx context.Context, uid uint, oid uint) (StatusMessage, error) {
var (
raw []byte
resp StatusMessage
err error
)

if raw, _, err = r.post(fmt.Sprintf("/api/users/%d/using/%d", uid, oid), nil, raw); err != nil {
if raw, _, err = r.post(ctx, fmt.Sprintf("/api/users/%d/using/%d", uid, oid), nil, raw); err != nil {
return StatusMessage{}, err
}
if err = json.Unmarshal(raw, &resp); err != nil {
Expand Down
10 changes: 6 additions & 4 deletions rest-admin_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sdk_test

import (
"context"
"testing"

"github.com/grafana-tools/sdk"
Expand All @@ -9,6 +10,7 @@ import (
func TestAdminOperations(t *testing.T) {
shouldSkip(t)
client := getClient(t)
ctx := context.Background()

u := sdk.User{
Login: "test",
Expand All @@ -19,7 +21,7 @@ func TestAdminOperations(t *testing.T) {
IsGrafanaAdmin: false,
}

st, err := client.CreateUser(u)
st, err := client.CreateUser(ctx, u)
if err != nil {
t.Fatalf("failed to create an user: %s", err.Error())
}
Expand All @@ -29,7 +31,7 @@ func TestAdminOperations(t *testing.T) {

uid := *st.ID

retrievedUser, err := client.GetUser(uid)
retrievedUser, err := client.GetUser(ctx, uid)
if err != nil {
t.Fatalf("failed to get user: %s", err.Error())
}
Expand All @@ -38,12 +40,12 @@ func TestAdminOperations(t *testing.T) {
t.Fatal("retrieved data does not match what was created")
}

_, err = client.UpdateUserPermissions(sdk.UserPermissions{IsGrafanaAdmin: true}, uid)
_, err = client.UpdateUserPermissions(ctx, sdk.UserPermissions{IsGrafanaAdmin: true}, uid)
if err != nil {
t.Fatalf("failed to convert the user into an admin: %s", err)
}

retrievedUser, err = client.GetUser(uid)
retrievedUser, err = client.GetUser(ctx, uid)
if err != nil {
t.Fatalf("failed to get user: %s", err.Error())
}
Expand Down
33 changes: 17 additions & 16 deletions rest-alertnotification.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,21 @@ package sdk
*/

import (
"context"
"encoding/json"
"fmt"
)

// GetAllAlertNotifications gets all alert notification channels.
// Reflects GET /api/alert-notifications API call.
func (c *Client) GetAllAlertNotifications() ([]AlertNotification, error) {
func (c *Client) GetAllAlertNotifications(ctx context.Context) ([]AlertNotification, error) {
var (
raw []byte
an []AlertNotification
code int
err error
)
if raw, code, err = c.get("api/alert-notifications", nil); err != nil {
if raw, code, err = c.get(ctx, "api/alert-notifications", nil); err != nil {
return nil, err
}
if code != 200 {
Expand All @@ -42,14 +43,14 @@ func (c *Client) GetAllAlertNotifications() ([]AlertNotification, error) {

// GetAlertNotificationUID gets the alert notification channel which has the specified uid.
// Reflects GET /api/alert-notifications/uid/:uid API call.
func (c *Client) GetAlertNotificationUID(uid string) (AlertNotification, error) {
func (c *Client) GetAlertNotificationUID(ctx context.Context, uid string) (AlertNotification, error) {
var (
raw []byte
an AlertNotification
code int
err error
)
if raw, code, err = c.get(fmt.Sprintf("api/alert-notifications/uid/%s", uid), nil); err != nil {
if raw, code, err = c.get(ctx, fmt.Sprintf("api/alert-notifications/uid/%s", uid), nil); err != nil {
return an, err
}
if code != 200 {
Expand All @@ -61,14 +62,14 @@ func (c *Client) GetAlertNotificationUID(uid string) (AlertNotification, error)

// GetAlertNotificationID gets the alert notification channel which has the specified id.
// Reflects GET /api/alert-notifications/:id API call.
func (c *Client) GetAlertNotificationID(id uint) (AlertNotification, error) {
func (c *Client) GetAlertNotificationID(ctx context.Context, id uint) (AlertNotification, error) {
var (
raw []byte
an AlertNotification
code int
err error
)
if raw, code, err = c.get(fmt.Sprintf("api/alert-notifications/%d", id), nil); err != nil {
if raw, code, err = c.get(ctx, fmt.Sprintf("api/alert-notifications/%d", id), nil); err != nil {
return an, err
}
if code != 200 {
Expand All @@ -80,7 +81,7 @@ func (c *Client) GetAlertNotificationID(id uint) (AlertNotification, error) {

// CreateAlertNotification creates a new alert notification channel.
// Reflects POST /api/alert-notifications API call.
func (c *Client) CreateAlertNotification(an AlertNotification) (int64, error) {
func (c *Client) CreateAlertNotification(ctx context.Context, an AlertNotification) (int64, error) {
var (
raw []byte
code int
Expand All @@ -89,7 +90,7 @@ func (c *Client) CreateAlertNotification(an AlertNotification) (int64, error) {
if raw, err = json.Marshal(an); err != nil {
return -1, err
}
if raw, code, err = c.post(fmt.Sprintf("api/alert-notifications"), nil, raw); err != nil {
if raw, code, err = c.post(ctx, fmt.Sprintf("api/alert-notifications"), nil, raw); err != nil {
return -1, err
}
if code != 200 {
Expand All @@ -104,7 +105,7 @@ func (c *Client) CreateAlertNotification(an AlertNotification) (int64, error) {

// UpdateAlertNotificationUID updates the specified alert notification channel.
// Reflects PUT /api/alert-notifications/uid/:uid API call.
func (c *Client) UpdateAlertNotificationUID(an AlertNotification, uid string) error {
func (c *Client) UpdateAlertNotificationUID(ctx context.Context, an AlertNotification, uid string) error {
var (
raw []byte
code int
Expand All @@ -113,7 +114,7 @@ func (c *Client) UpdateAlertNotificationUID(an AlertNotification, uid string) er
if raw, err = json.Marshal(an); err != nil {
return err
}
if raw, code, err = c.put(fmt.Sprintf("api/alert-notifications/uid/%s", uid), nil, raw); err != nil {
if raw, code, err = c.put(ctx, fmt.Sprintf("api/alert-notifications/uid/%s", uid), nil, raw); err != nil {
return err
}
if code != 200 {
Expand All @@ -124,7 +125,7 @@ func (c *Client) UpdateAlertNotificationUID(an AlertNotification, uid string) er

// UpdateAlertNotificationID updates the specified alert notification channel.
// Reflects PUT /api/alert-notifications/:id API call.
func (c *Client) UpdateAlertNotificationID(an AlertNotification, id uint) error {
func (c *Client) UpdateAlertNotificationID(ctx context.Context, an AlertNotification, id uint) error {
var (
raw []byte
code int
Expand All @@ -133,7 +134,7 @@ func (c *Client) UpdateAlertNotificationID(an AlertNotification, id uint) error
if raw, err = json.Marshal(an); err != nil {
return err
}
if raw, code, err = c.put(fmt.Sprintf("api/alert-notifications/%d", id), nil, raw); err != nil {
if raw, code, err = c.put(ctx, fmt.Sprintf("api/alert-notifications/%d", id), nil, raw); err != nil {
return err
}
if code != 200 {
Expand All @@ -144,13 +145,13 @@ func (c *Client) UpdateAlertNotificationID(an AlertNotification, id uint) error

// DeleteAlertNotificationUID deletes the specified alert notification channel.
// Reflects DELETE /api/alert-notifications/uid/:uid API call.
func (c *Client) DeleteAlertNotificationUID(uid string) error {
func (c *Client) DeleteAlertNotificationUID(ctx context.Context, uid string) error {
var (
raw []byte
code int
err error
)
if raw, code, err = c.delete(fmt.Sprintf("api/alert-notifications/uid/%s", uid)); err != nil {
if raw, code, err = c.delete(ctx, fmt.Sprintf("api/alert-notifications/uid/%s", uid)); err != nil {
return err
}
if code != 200 {
Expand All @@ -161,13 +162,13 @@ func (c *Client) DeleteAlertNotificationUID(uid string) error {

// DeleteAlertNotificationID deletes the specified alert notification channel.
// Reflects DELETE /api/alert-notifications/:id API call.
func (c *Client) DeleteAlertNotificationID(id uint) error {
func (c *Client) DeleteAlertNotificationID(ctx context.Context, id uint) error {
var (
raw []byte
code int
err error
)
if raw, code, err = c.delete(fmt.Sprintf("api/alert-notifications/%d", id)); err != nil {
if raw, code, err = c.delete(ctx, fmt.Sprintf("api/alert-notifications/%d", id)); err != nil {
return err
}
if code != 200 {
Expand Down
Loading

0 comments on commit f0431e4

Please sign in to comment.