The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/api/datasources.go

219 lines
4.9 KiB

package api
import (
"sort"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/middleware"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/util"
)
func GetDataSources(c *middleware.Context) {
query := m.GetDataSourcesQuery{OrgId: c.OrgId}
if err := bus.Dispatch(&query); err != nil {
c.JsonApiErr(500, "Failed to query datasources", err)
return
}
result := make(dtos.DataSourceList, 0)
for _, ds := range query.Result {
dsItem := dtos.DataSource{
Id: ds.Id,
OrgId: ds.OrgId,
Name: ds.Name,
Url: ds.Url,
Type: ds.Type,
Access: ds.Access,
Password: ds.Password,
Database: ds.Database,
User: ds.User,
BasicAuth: ds.BasicAuth,
IsDefault: ds.IsDefault,
JsonData: ds.JsonData,
}
if plugin, exists := plugins.DataSources[ds.Type]; exists {
dsItem.TypeLogoUrl = plugin.Info.Logos.Small
} else {
dsItem.TypeLogoUrl = "public/img/icn-datasource.svg"
}
result = append(result, dsItem)
}
sort.Sort(result)
c.JSON(200, result)
}
func GetDataSourceById(c *middleware.Context) Response {
query := m.GetDataSourceByIdQuery{
Id: c.ParamsInt64(":id"),
OrgId: c.OrgId,
}
if err := bus.Dispatch(&query); err != nil {
if err == m.ErrDataSourceNotFound {
return ApiError(404, "Data source not found", nil)
}
return ApiError(500, "Failed to query datasources", err)
}
ds := query.Result
dtos := convertModelToDtos(ds)
return Json(200, &dtos)
}
func DeleteDataSource(c *middleware.Context) {
id := c.ParamsInt64(":id")
if id <= 0 {
c.JsonApiErr(400, "Missing valid datasource id", nil)
return
}
cmd := &m.DeleteDataSourceCommand{Id: id, OrgId: c.OrgId}
err := bus.Dispatch(cmd)
if err != nil {
c.JsonApiErr(500, "Failed to delete datasource", err)
return
}
c.JsonOK("Data source deleted")
}
func AddDataSource(c *middleware.Context, cmd m.AddDataSourceCommand) {
cmd.OrgId = c.OrgId
if err := bus.Dispatch(&cmd); err != nil {
if err == m.ErrDataSourceNameExists {
c.JsonApiErr(409, err.Error(), err)
return
}
c.JsonApiErr(500, "Failed to add datasource", err)
return
}
c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id})
}
func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) Response {
cmd.OrgId = c.OrgId
cmd.Id = c.ParamsInt64(":id")
err := fillWithSecureJsonData(&cmd)
if err != nil {
return ApiError(500, "Failed to update datasource", err)
}
err = bus.Dispatch(&cmd)
if err != nil {
return ApiError(500, "Failed to update datasource", err)
}
return Json(200, util.DynMap{"message": "Datasource updated"})
}
func fillWithSecureJsonData(cmd *m.UpdateDataSourceCommand) error {
if len(cmd.SecureJsonData) == 0 {
return nil
}
ds, err := getRawDataSourceById(cmd.Id, cmd.OrgId)
if err != nil {
return err
}
secureJsonData := ds.SecureJsonData.Decrypt()
for k, v := range secureJsonData {
if _, ok := cmd.SecureJsonData[k]; !ok {
cmd.SecureJsonData[k] = v
}
}
return nil
}
func getRawDataSourceById(id int64, orgId int64) (*m.DataSource, error) {
query := m.GetDataSourceByIdQuery{
Id: id,
OrgId: orgId,
}
if err := bus.Dispatch(&query); err != nil {
return nil, err
}
return query.Result, nil
}
// Get /api/datasources/name/:name
func GetDataSourceByName(c *middleware.Context) Response {
query := m.GetDataSourceByNameQuery{Name: c.Params(":name"), OrgId: c.OrgId}
if err := bus.Dispatch(&query); err != nil {
if err == m.ErrDataSourceNotFound {
return ApiError(404, "Data source not found", nil)
}
return ApiError(500, "Failed to query datasources", err)
}
dtos := convertModelToDtos(query.Result)
return Json(200, &dtos)
}
// Get /api/datasources/id/:name
func GetDataSourceIdByName(c *middleware.Context) Response {
query := m.GetDataSourceByNameQuery{Name: c.Params(":name"), OrgId: c.OrgId}
if err := bus.Dispatch(&query); err != nil {
if err == m.ErrDataSourceNotFound {
return ApiError(404, "Data source not found", nil)
}
return ApiError(500, "Failed to query datasources", err)
}
ds := query.Result
dtos := dtos.AnyId{
Id: ds.Id,
}
return Json(200, &dtos)
}
func convertModelToDtos(ds *m.DataSource) dtos.DataSource {
dto := dtos.DataSource{
Id: ds.Id,
OrgId: ds.OrgId,
Name: ds.Name,
Url: ds.Url,
Type: ds.Type,
Access: ds.Access,
Password: ds.Password,
Database: ds.Database,
User: ds.User,
BasicAuth: ds.BasicAuth,
BasicAuthUser: ds.BasicAuthUser,
BasicAuthPassword: ds.BasicAuthPassword,
WithCredentials: ds.WithCredentials,
IsDefault: ds.IsDefault,
JsonData: ds.JsonData,
SecureJsonFields: map[string]bool{},
}
for k, v := range ds.SecureJsonData {
if len(v) > 0 {
dto.SecureJsonFields[k] = true
}
}
return dto
}