| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-03-18 19:08:52 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2016-03-16 03:29:35 +08:00
										 |  |  | 	"sort" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 17:37:13 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/dtos" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/bus" | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2016-12-07 18:10:42 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins" | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins/backendplugin" | 
					
						
							| 
									
										
										
										
											2015-06-01 18:15:49 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func GetDataSources(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 	query := models.GetDataSourcesQuery{OrgId: c.OrgId} | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-14 17:04:27 +08:00
										 |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to query datasources", err) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-16 03:29:35 +08:00
										 |  |  | 	result := make(dtos.DataSourceList, 0) | 
					
						
							| 
									
										
										
										
											2018-10-17 21:58:52 +08:00
										 |  |  | 	for _, ds := range query.Result { | 
					
						
							| 
									
										
										
										
											2017-04-25 21:17:49 +08:00
										 |  |  | 		dsItem := dtos.DataSourceListItemDTO{ | 
					
						
							| 
									
										
										
										
											2015-02-24 03:07:49 +08:00
										 |  |  | 			OrgId:     ds.OrgId, | 
					
						
							| 
									
										
										
										
											2018-10-01 21:38:55 +08:00
										 |  |  | 			Id:        ds.Id, | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 			Name:      ds.Name, | 
					
						
							|  |  |  | 			Url:       ds.Url, | 
					
						
							|  |  |  | 			Type:      ds.Type, | 
					
						
							|  |  |  | 			Access:    ds.Access, | 
					
						
							|  |  |  | 			Password:  ds.Password, | 
					
						
							|  |  |  | 			Database:  ds.Database, | 
					
						
							|  |  |  | 			User:      ds.User, | 
					
						
							|  |  |  | 			BasicAuth: ds.BasicAuth, | 
					
						
							| 
									
										
										
										
											2015-01-09 23:36:23 +08:00
										 |  |  | 			IsDefault: ds.IsDefault, | 
					
						
							| 
									
										
										
										
											2016-09-01 23:21:13 +08:00
										 |  |  | 			JsonData:  ds.JsonData, | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 			ReadOnly:  ds.ReadOnly, | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-16 03:29:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if plugin, exists := plugins.DataSources[ds.Type]; exists { | 
					
						
							|  |  |  | 			dsItem.TypeLogoUrl = plugin.Info.Logos.Small | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-03-23 22:09:48 +08:00
										 |  |  | 			dsItem.TypeLogoUrl = "public/img/icn-datasource.svg" | 
					
						
							| 
									
										
										
										
											2016-03-16 03:29:35 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		result = append(result, dsItem) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-16 03:29:35 +08:00
										 |  |  | 	sort.Sort(result) | 
					
						
							| 
									
										
										
										
											2017-02-08 21:20:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, &result) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func GetDataSourceById(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 	query := models.GetDataSourceByIdQuery{ | 
					
						
							| 
									
										
										
										
											2015-02-24 03:07:49 +08:00
										 |  |  | 		Id:    c.ParamsInt64(":id"), | 
					
						
							|  |  |  | 		OrgId: c.OrgId, | 
					
						
							| 
									
										
										
										
											2015-02-14 17:04:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceNotFound { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 			return Error(404, "Data source not found", nil) | 
					
						
							| 
									
										
										
										
											2015-11-13 16:43:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to query datasources", err) | 
					
						
							| 
									
										
										
										
											2015-02-14 17:04:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ds := query.Result | 
					
						
							| 
									
										
										
										
											2016-03-08 18:51:03 +08:00
										 |  |  | 	dtos := convertModelToDtos(ds) | 
					
						
							| 
									
										
										
										
											2015-02-14 17:04:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, &dtos) | 
					
						
							| 
									
										
										
										
											2015-02-14 17:04:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func DeleteDataSourceById(c *models.ReqContext) Response { | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	id := c.ParamsInt64(":id") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if id <= 0 { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(400, "Missing valid datasource id", nil) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-01 21:38:55 +08:00
										 |  |  | 	ds, err := getRawDataSourceById(id, c.OrgId) | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(400, "Failed to delete datasource", nil) | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ds.ReadOnly { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(403, "Cannot delete read-only data source", nil) | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 	cmd := &models.DeleteDataSourceByIdCommand{Id: id, OrgId: c.OrgId} | 
					
						
							| 
									
										
										
										
											2017-02-10 10:11:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	err = bus.Dispatch(cmd) | 
					
						
							| 
									
										
										
										
											2017-02-10 10:11:36 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to delete datasource", err) | 
					
						
							| 
									
										
										
										
											2017-02-10 10:11:36 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return Success("Data source deleted") | 
					
						
							| 
									
										
										
										
											2017-02-10 10:11:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func DeleteDataSourceByName(c *models.ReqContext) Response { | 
					
						
							| 
									
										
										
										
											2017-02-10 10:11:36 +08:00
										 |  |  | 	name := c.Params(":name") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if name == "" { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(400, "Missing valid datasource name", nil) | 
					
						
							| 
									
										
										
										
											2017-02-10 10:11:36 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 	getCmd := &models.GetDataSourceByNameQuery{Name: name, OrgId: c.OrgId} | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	if err := bus.Dispatch(getCmd); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceNotFound { | 
					
						
							| 
									
										
										
										
											2018-06-23 10:15:36 +08:00
										 |  |  | 			return Error(404, "Data source not found", nil) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to delete datasource", err) | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if getCmd.Result.ReadOnly { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(403, "Cannot delete read-only data source", nil) | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 	cmd := &models.DeleteDataSourceByNameCommand{Name: name, OrgId: c.OrgId} | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	err := bus.Dispatch(cmd) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to delete datasource", err) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return Success("Data source deleted") | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) Response { | 
					
						
							| 
									
										
										
										
											2015-02-24 03:07:49 +08:00
										 |  |  | 	cmd.OrgId = c.OrgId | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-09 18:01:37 +08:00
										 |  |  | 	if err := bus.Dispatch(&cmd); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceNameExists { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 			return Error(409, err.Error(), err) | 
					
						
							| 
									
										
										
										
											2016-10-01 22:41:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to add datasource", err) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 23:28:54 +08:00
										 |  |  | 	ds := convertModelToDtos(cmd.Result) | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, util.DynMap{ | 
					
						
							| 
									
										
										
										
											2017-10-19 23:28:54 +08:00
										 |  |  | 		"message":    "Datasource added", | 
					
						
							|  |  |  | 		"id":         cmd.Result.Id, | 
					
						
							|  |  |  | 		"name":       cmd.Result.Name, | 
					
						
							|  |  |  | 		"datasource": ds, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func UpdateDataSource(c *models.ReqContext, cmd models.UpdateDataSourceCommand) Response { | 
					
						
							| 
									
										
										
										
											2015-02-24 03:07:49 +08:00
										 |  |  | 	cmd.OrgId = c.OrgId | 
					
						
							| 
									
										
										
										
											2015-06-01 18:15:49 +08:00
										 |  |  | 	cmd.Id = c.ParamsInt64(":id") | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-22 19:37:35 +08:00
										 |  |  | 	err := fillWithSecureJSONData(&cmd) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to update datasource", err) | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = bus.Dispatch(&cmd) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceUpdatingOldVersion { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 			return Error(500, "Failed to update datasource. Reload new version and try again", err) | 
					
						
							| 
									
										
										
										
											2017-10-19 23:28:54 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to update datasource", err) | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-08-07 23:56:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 	query := models.GetDataSourceByIdQuery{ | 
					
						
							| 
									
										
										
										
											2018-08-07 23:56:02 +08:00
										 |  |  | 		Id:    cmd.Id, | 
					
						
							|  |  |  | 		OrgId: c.OrgId, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceNotFound { | 
					
						
							| 
									
										
										
										
											2018-08-07 23:56:02 +08:00
										 |  |  | 			return Error(404, "Data source not found", nil) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return Error(500, "Failed to query datasources", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dtos := convertModelToDtos(query.Result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, util.DynMap{ | 
					
						
							| 
									
										
										
										
											2017-10-19 23:28:54 +08:00
										 |  |  | 		"message":    "Datasource updated", | 
					
						
							|  |  |  | 		"id":         cmd.Id, | 
					
						
							|  |  |  | 		"name":       cmd.Name, | 
					
						
							| 
									
										
										
										
											2018-08-07 23:56:02 +08:00
										 |  |  | 		"datasource": dtos, | 
					
						
							| 
									
										
										
										
											2017-10-19 23:28:54 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func fillWithSecureJSONData(cmd *models.UpdateDataSourceCommand) error { | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	if len(cmd.SecureJsonData) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-01 21:38:55 +08:00
										 |  |  | 	ds, err := getRawDataSourceById(cmd.Id, cmd.OrgId) | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	if ds.ReadOnly { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		return models.ErrDatasourceIsReadOnly | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-22 19:37:35 +08:00
										 |  |  | 	secureJSONData := ds.SecureJsonData.Decrypt() | 
					
						
							|  |  |  | 	for k, v := range secureJSONData { | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if _, ok := cmd.SecureJsonData[k]; !ok { | 
					
						
							|  |  |  | 			cmd.SecureJsonData[k] = v | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func getRawDataSourceById(id int64, orgID int64) (*models.DataSource, error) { | 
					
						
							|  |  |  | 	query := models.GetDataSourceByIdQuery{ | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 		Id:    id, | 
					
						
							| 
									
										
										
										
											2018-03-22 19:37:35 +08:00
										 |  |  | 		OrgId: orgID, | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return query.Result, nil | 
					
						
							| 
									
										
										
										
											2014-12-29 20:36:08 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-28 15:25:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | // Get /api/datasources/name/:name
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func GetDataSourceByName(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 	query := models.GetDataSourceByNameQuery{Name: c.Params(":name"), OrgId: c.OrgId} | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceNotFound { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 			return Error(404, "Data source not found", nil) | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to query datasources", err) | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-06 23:11:46 +08:00
										 |  |  | 	dtos := convertModelToDtos(query.Result) | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, &dtos) | 
					
						
							| 
									
										
										
										
											2016-03-08 18:51:03 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-10 17:31:10 +08:00
										 |  |  | // Get /api/datasources/id/:name
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func GetDataSourceIdByName(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 	query := models.GetDataSourceByNameQuery{Name: c.Params(":name"), OrgId: c.OrgId} | 
					
						
							| 
									
										
										
										
											2016-03-10 17:31:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&query); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceNotFound { | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 			return Error(404, "Data source not found", nil) | 
					
						
							| 
									
										
										
										
											2016-03-10 17:31:10 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 		return Error(500, "Failed to query datasources", err) | 
					
						
							| 
									
										
										
										
											2016-03-10 17:31:10 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ds := query.Result | 
					
						
							|  |  |  | 	dtos := dtos.AnyId{ | 
					
						
							|  |  |  | 		Id: ds.Id, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 05:13:46 +08:00
										 |  |  | 	return JSON(200, &dtos) | 
					
						
							| 
									
										
										
										
											2016-03-10 17:31:10 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | // /api/datasources/:id/resources/*
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func (hs *HTTPServer) CallDatasourceResource(c *models.ReqContext) { | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | 	datasourceID := c.ParamsInt64(":id") | 
					
						
							|  |  |  | 	ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 		if err == models.ErrDataSourceAccessDenied { | 
					
						
							| 
									
										
										
										
											2020-03-03 18:45:16 +08:00
										 |  |  | 			c.JsonApiErr(403, "Access denied to datasource", err) | 
					
						
							|  |  |  | 			return | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-03-03 18:45:16 +08:00
										 |  |  | 		c.JsonApiErr(500, "Unable to load datasource meta data", err) | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// find plugin
 | 
					
						
							|  |  |  | 	plugin, ok := plugins.DataSources[ds.Type] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-03-03 18:45:16 +08:00
										 |  |  | 		c.JsonApiErr(500, "Unable to find datasource plugin", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	config := backendplugin.PluginConfig{ | 
					
						
							| 
									
										
										
										
											2020-03-10 22:18:27 +08:00
										 |  |  | 		OrgID:    c.OrgId, | 
					
						
							|  |  |  | 		PluginID: plugin.Id, | 
					
						
							| 
									
										
										
										
											2020-03-03 18:45:16 +08:00
										 |  |  | 		DataSourceConfig: &backendplugin.DataSourceConfig{ | 
					
						
							| 
									
										
										
										
											2020-03-10 22:18:27 +08:00
										 |  |  | 			ID:                      ds.Id, | 
					
						
							|  |  |  | 			Name:                    ds.Name, | 
					
						
							|  |  |  | 			URL:                     ds.Url, | 
					
						
							|  |  |  | 			Database:                ds.Database, | 
					
						
							|  |  |  | 			User:                    ds.User, | 
					
						
							|  |  |  | 			BasicAuthEnabled:        ds.BasicAuth, | 
					
						
							|  |  |  | 			BasicAuthUser:           ds.BasicAuthUser, | 
					
						
							|  |  |  | 			JSONData:                ds.JsonData, | 
					
						
							|  |  |  | 			DecryptedSecureJSONData: ds.DecryptedValues(), | 
					
						
							|  |  |  | 			Updated:                 ds.Updated, | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-03 18:45:16 +08:00
										 |  |  | 	hs.BackendPluginManager.CallResource(config, c, c.Params("*")) | 
					
						
							| 
									
										
										
										
											2020-01-31 18:15:50 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | func convertModelToDtos(ds *models.DataSource) dtos.DataSource { | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	dto := dtos.DataSource{ | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | 		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, | 
					
						
							| 
									
										
										
										
											2016-12-15 04:05:12 +08:00
										 |  |  | 		SecureJsonFields:  map[string]bool{}, | 
					
						
							| 
									
										
										
										
											2017-10-19 23:28:54 +08:00
										 |  |  | 		Version:           ds.Version, | 
					
						
							| 
									
										
										
										
											2017-10-24 21:28:39 +08:00
										 |  |  | 		ReadOnly:          ds.ReadOnly, | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-24 23:24:47 +08:00
										 |  |  | 	for k, v := range ds.SecureJsonData { | 
					
						
							|  |  |  | 		if len(v) > 0 { | 
					
						
							| 
									
										
										
										
											2016-12-15 04:05:12 +08:00
										 |  |  | 			dto.SecureJsonFields[k] = true | 
					
						
							| 
									
										
										
										
											2016-11-24 23:24:47 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-18 23:44:59 +08:00
										 |  |  | 	return dto | 
					
						
							| 
									
										
										
										
											2016-03-08 04:25:26 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-03-13 19:31:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // CheckDatasourceHealth sends a health check request to the plugin datasource
 | 
					
						
							|  |  |  | // /api/datasource/:id/health
 | 
					
						
							|  |  |  | func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) { | 
					
						
							|  |  |  | 	datasourceID := c.ParamsInt64("id") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if err == models.ErrDataSourceAccessDenied { | 
					
						
							|  |  |  | 			c.JsonApiErr(403, "Access denied to datasource", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		c.JsonApiErr(500, "Unable to load datasource metadata", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	plugin, ok := hs.PluginManager.GetDatasource(ds.Type) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		c.JsonApiErr(500, "Unable to find datasource plugin", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	config := &backendplugin.PluginConfig{ | 
					
						
							|  |  |  | 		OrgID:    c.OrgId, | 
					
						
							|  |  |  | 		PluginID: plugin.Id, | 
					
						
							|  |  |  | 		DataSourceConfig: &backendplugin.DataSourceConfig{ | 
					
						
							|  |  |  | 			ID:                      ds.Id, | 
					
						
							|  |  |  | 			Name:                    ds.Name, | 
					
						
							|  |  |  | 			URL:                     ds.Url, | 
					
						
							|  |  |  | 			Database:                ds.Database, | 
					
						
							|  |  |  | 			User:                    ds.User, | 
					
						
							|  |  |  | 			BasicAuthEnabled:        ds.BasicAuth, | 
					
						
							|  |  |  | 			BasicAuthUser:           ds.BasicAuthUser, | 
					
						
							|  |  |  | 			JSONData:                ds.JsonData, | 
					
						
							|  |  |  | 			DecryptedSecureJSONData: ds.DecryptedValues(), | 
					
						
							|  |  |  | 			Updated:                 ds.Updated, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp, err := hs.BackendPluginManager.CheckHealth(c.Req.Context(), config) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if err == backendplugin.ErrPluginNotRegistered { | 
					
						
							|  |  |  | 			c.JsonApiErr(404, "Plugin not found", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Return status unknown instead?
 | 
					
						
							|  |  |  | 		if err == backendplugin.ErrDiagnosticsNotSupported { | 
					
						
							|  |  |  | 			c.JsonApiErr(404, "Health check not implemented", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Return status unknown or error instead?
 | 
					
						
							|  |  |  | 		if err == backendplugin.ErrHealthCheckFailed { | 
					
						
							|  |  |  | 			c.JsonApiErr(500, "Plugin health check failed", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		c.JsonApiErr(500, "Plugin healthcheck returned an unknown error", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 19:08:52 +08:00
										 |  |  | 	var jsonDetails map[string]interface{} | 
					
						
							| 
									
										
										
										
											2020-03-13 19:31:44 +08:00
										 |  |  | 	payload := map[string]interface{}{ | 
					
						
							| 
									
										
										
										
											2020-03-18 19:08:52 +08:00
										 |  |  | 		"status":  resp.Status.String(), | 
					
						
							|  |  |  | 		"message": resp.Message, | 
					
						
							|  |  |  | 		"details": jsonDetails, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Unmarshal JSONDetails if it's not empty.
 | 
					
						
							|  |  |  | 	if len(resp.JSONDetails) > 0 { | 
					
						
							|  |  |  | 		err = json.Unmarshal(resp.JSONDetails, &jsonDetails) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			c.JsonApiErr(500, "Failed to unmarshal detailed response from backend plugin", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		payload["details"] = jsonDetails | 
					
						
							| 
									
										
										
										
											2020-03-13 19:31:44 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if resp.Status != backendplugin.HealthStatusOk { | 
					
						
							|  |  |  | 		c.JSON(503, payload) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.JSON(200, payload) | 
					
						
							|  |  |  | } |