diff --git a/datasource.go b/datasource.go index fe582fd2..65df70f1 100644 --- a/datasource.go +++ b/datasource.go @@ -23,6 +23,7 @@ package sdk // http://docs.grafana.org/reference/http_api/#get-all-datasources type Datasource struct { ID uint `json:"id"` + UID string `json:"uid"` OrgID uint `json:"orgId"` Name string `json:"name"` Type string `json:"type"` diff --git a/errors.go b/errors.go new file mode 100644 index 00000000..50e468a2 --- /dev/null +++ b/errors.go @@ -0,0 +1,11 @@ +package sdk + +// ErrNotFound is the error returned when 404 HTTP status returned +type ErrNotFound struct { + Message string +} + +// Error implements the error interface for ErrNotFound. +func (e ErrNotFound) Error() string { + return e.Message +} diff --git a/rest-datasource.go b/rest-datasource.go index f5feee5d..bf35af74 100644 --- a/rest-datasource.go +++ b/rest-datasource.go @@ -82,6 +82,28 @@ func (r *Client) GetDatasourceByName(ctx context.Context, name string) (Datasour return ds, err } +// GetDatasourceByUID gets an datasource by UID. +// Reflects GET /api/datasources/uid/:datasourceUID API call. +func (r *Client) GetDatasourceByUID(ctx context.Context, uid string) (Datasource, error) { + var ( + raw []byte + ds Datasource + code int + err error + ) + if raw, code, err = r.get(ctx, fmt.Sprintf("api/datasources/uid/%s", uid), nil); err != nil { + return ds, err + } + if code == 404 { + return ds, ErrNotFound{Message: fmt.Sprintf("Datasource with UID %s not found", uid)} + } + if code != 200 { + return ds, fmt.Errorf("HTTP error %d: returns %s", code, raw) + } + err = json.Unmarshal(raw, &ds) + return ds, err +} + // CreateDatasource creates a new datasource. // Reflects POST /api/datasources API call. func (r *Client) CreateDatasource(ctx context.Context, ds Datasource) (StatusMessage, error) { @@ -152,6 +174,21 @@ func (r *Client) DeleteDatasourceByName(ctx context.Context, name string) (Statu return reply, err } +// DeleteDatasourceByUID deletes an existing datasource by UID. +// Reflects DELETE /api/datasources/uid/:datasourceUID API call. +func (r *Client) DeleteDatasourceByUID(ctx context.Context, uid string) (StatusMessage, error) { + var ( + raw []byte + reply StatusMessage + err error + ) + if raw, _, err = r.delete(ctx, fmt.Sprintf("api/datasources/uid/%s", uid)); err != nil { + return StatusMessage{}, err + } + err = json.Unmarshal(raw, &reply) + return reply, err +} + // GetDatasourceTypes gets all available plugins for the datasources. // Reflects GET /api/datasources/plugins API call. func (r *Client) GetDatasourceTypes(ctx context.Context) (map[string]DatasourceType, error) { diff --git a/rest-datasource_integration_test.go b/rest-datasource_integration_test.go index 59f59454..0a4fcf5e 100644 --- a/rest-datasource_integration_test.go +++ b/rest-datasource_integration_test.go @@ -2,6 +2,7 @@ package sdk_test import ( "context" + "errors" "testing" "github.com/grafana-tools/sdk" @@ -23,6 +24,7 @@ func Test_Datasource_CRUD(t *testing.T) { db := "grafanasdk" ds := sdk.Datasource{ + UID: "datasource_uid", Name: "elastic_datasource", Type: "elasticsearch", IsDefault: false, @@ -50,6 +52,24 @@ func Test_Datasource_CRUD(t *testing.T) { t.Fatalf("got wrong name: expected %s, was %s", dsRetrieved.Name, ds.Name) } + dsRetrieved, err = client.GetDatasourceByUID(ctx, "datasource_uid") + if err != nil { + t.Fatal(err) + } + + if dsRetrieved.Name != ds.Name { + t.Fatalf("got wrong name: expected %s, was %s", dsRetrieved.Name, ds.Name) + } + + dsRetrieved, err = client.GetDatasourceByName(ctx, "elastic_datasource") + if err != nil { + t.Fatal(err) + } + + if dsRetrieved.Name != ds.Name { + t.Fatalf("got wrong name: expected %s, was %s", dsRetrieved.Name, ds.Name) + } + ds.Name = "elasticsdksource" ds.ID = dsRetrieved.ID status, err = client.UpdateDatasource(ctx, ds) @@ -66,4 +86,10 @@ func Test_Datasource_CRUD(t *testing.T) { if err == nil { t.Fatalf("expected the datasource to be deleted") } + + _, err = client.GetDatasourceByUID(ctx, "datasource_uid") + if !errors.As(err, &sdk.ErrNotFound{}) { + t.Fatalf("expected error not found") + } + }