|
|
|
@ -8,129 +8,20 @@ import ( |
|
|
|
|
"github.com/grafana/grafana/pkg/plugins" |
|
|
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol" |
|
|
|
|
"github.com/grafana/grafana/pkg/services/licensing" |
|
|
|
|
"github.com/grafana/grafana/pkg/services/pluginsettings" |
|
|
|
|
"github.com/grafana/grafana/pkg/setting" |
|
|
|
|
"github.com/grafana/grafana/pkg/tsdb/grafanads" |
|
|
|
|
"github.com/grafana/grafana/pkg/util" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]plugins.DataSourceDTO, error) { |
|
|
|
|
orgDataSources := make([]*models.DataSource, 0) |
|
|
|
|
|
|
|
|
|
if c.OrgId != 0 { |
|
|
|
|
query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit} |
|
|
|
|
err := hs.SQLStore.GetDataSources(c.Req.Context(), &query) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
filtered, err := hs.filterDatasourcesByQueryPermission(c.Req.Context(), c.SignedInUser, query.Result) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
orgDataSources = filtered |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dataSources := make(map[string]plugins.DataSourceDTO) |
|
|
|
|
|
|
|
|
|
for _, ds := range orgDataSources { |
|
|
|
|
url := ds.Url |
|
|
|
|
|
|
|
|
|
if ds.Access == models.DS_ACCESS_PROXY { |
|
|
|
|
url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dsDTO := plugins.DataSourceDTO{ |
|
|
|
|
ID: ds.Id, |
|
|
|
|
UID: ds.Uid, |
|
|
|
|
Type: ds.Type, |
|
|
|
|
Name: ds.Name, |
|
|
|
|
URL: url, |
|
|
|
|
IsDefault: ds.IsDefault, |
|
|
|
|
Access: string(ds.Access), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
plugin, exists := enabledPlugins.Get(plugins.DataSource, ds.Type) |
|
|
|
|
if !exists { |
|
|
|
|
c.Logger.Error("Could not find plugin definition for data source", "datasource_type", ds.Type) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
dsDTO.Preload = plugin.Preload |
|
|
|
|
dsDTO.Module = plugin.Module |
|
|
|
|
dsDTO.PluginMeta = &plugins.PluginMetaDTO{ |
|
|
|
|
JSONData: plugin.JSONData, |
|
|
|
|
Signature: plugin.Signature, |
|
|
|
|
Module: plugin.Module, |
|
|
|
|
BaseURL: plugin.BaseURL, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.JsonData == nil { |
|
|
|
|
dsDTO.JSONData = make(map[string]interface{}) |
|
|
|
|
} else { |
|
|
|
|
dsDTO.JSONData = ds.JsonData.MustMap() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Access == models.DS_ACCESS_DIRECT { |
|
|
|
|
if ds.BasicAuth { |
|
|
|
|
dsDTO.BasicAuth = util.GetBasicAuthHeader( |
|
|
|
|
ds.BasicAuthUser, |
|
|
|
|
hs.DataSourcesService.DecryptedBasicAuthPassword(ds), |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
if ds.WithCredentials { |
|
|
|
|
dsDTO.WithCredentials = ds.WithCredentials |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Type == models.DS_INFLUXDB_08 { |
|
|
|
|
dsDTO.Username = ds.User |
|
|
|
|
dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) |
|
|
|
|
dsDTO.URL = url + "/db/" + ds.Database |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Type == models.DS_INFLUXDB { |
|
|
|
|
dsDTO.Username = ds.User |
|
|
|
|
dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) |
|
|
|
|
dsDTO.URL = url |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ds.Type == models.DS_INFLUXDB) || (ds.Type == models.DS_ES) { |
|
|
|
|
dsDTO.Database = ds.Database |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Type == models.DS_PROMETHEUS { |
|
|
|
|
// add unproxied server URL for link to Prometheus web UI
|
|
|
|
|
ds.JsonData.Set("directUrl", ds.Url) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dataSources[ds.Name] = dsDTO |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// add data sources that are built in (meaning they are not added via data sources page, nor have any entry in
|
|
|
|
|
// the datasource table)
|
|
|
|
|
for _, ds := range hs.pluginStore.Plugins(c.Req.Context(), plugins.DataSource) { |
|
|
|
|
if ds.BuiltIn { |
|
|
|
|
dto := plugins.DataSourceDTO{ |
|
|
|
|
Type: string(ds.Type), |
|
|
|
|
Name: ds.Name, |
|
|
|
|
JSONData: make(map[string]interface{}), |
|
|
|
|
PluginMeta: &plugins.PluginMetaDTO{ |
|
|
|
|
JSONData: ds.JSONData, |
|
|
|
|
Signature: ds.Signature, |
|
|
|
|
Module: ds.Module, |
|
|
|
|
BaseURL: ds.BaseURL, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
if ds.Name == grafanads.DatasourceName { |
|
|
|
|
dto.ID = grafanads.DatasourceID |
|
|
|
|
dto.UID = grafanads.DatasourceUID |
|
|
|
|
} |
|
|
|
|
dataSources[ds.Name] = dto |
|
|
|
|
} |
|
|
|
|
func (hs *HTTPServer) GetFrontendSettings(c *models.ReqContext) { |
|
|
|
|
settings, err := hs.getFrontendSettingsMap(c) |
|
|
|
|
if err != nil { |
|
|
|
|
c.JsonApiErr(400, "Failed to get frontend settings", err) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return dataSources, nil |
|
|
|
|
c.JSON(200, settings) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// getFrontendSettingsMap returns a json object with all the settings needed for front end initialisation.
|
|
|
|
@ -290,6 +181,126 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i |
|
|
|
|
return jsonObj, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]plugins.DataSourceDTO, error) { |
|
|
|
|
orgDataSources := make([]*models.DataSource, 0) |
|
|
|
|
|
|
|
|
|
if c.OrgId != 0 { |
|
|
|
|
query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit} |
|
|
|
|
err := hs.SQLStore.GetDataSources(c.Req.Context(), &query) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
filtered, err := hs.filterDatasourcesByQueryPermission(c.Req.Context(), c.SignedInUser, query.Result) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
orgDataSources = filtered |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dataSources := make(map[string]plugins.DataSourceDTO) |
|
|
|
|
|
|
|
|
|
for _, ds := range orgDataSources { |
|
|
|
|
url := ds.Url |
|
|
|
|
|
|
|
|
|
if ds.Access == models.DS_ACCESS_PROXY { |
|
|
|
|
url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dsDTO := plugins.DataSourceDTO{ |
|
|
|
|
ID: ds.Id, |
|
|
|
|
UID: ds.Uid, |
|
|
|
|
Type: ds.Type, |
|
|
|
|
Name: ds.Name, |
|
|
|
|
URL: url, |
|
|
|
|
IsDefault: ds.IsDefault, |
|
|
|
|
Access: string(ds.Access), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
plugin, exists := enabledPlugins.Get(plugins.DataSource, ds.Type) |
|
|
|
|
if !exists { |
|
|
|
|
c.Logger.Error("Could not find plugin definition for data source", "datasource_type", ds.Type) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
dsDTO.Preload = plugin.Preload |
|
|
|
|
dsDTO.Module = plugin.Module |
|
|
|
|
dsDTO.PluginMeta = &plugins.PluginMetaDTO{ |
|
|
|
|
JSONData: plugin.JSONData, |
|
|
|
|
Signature: plugin.Signature, |
|
|
|
|
Module: plugin.Module, |
|
|
|
|
BaseURL: plugin.BaseURL, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.JsonData == nil { |
|
|
|
|
dsDTO.JSONData = make(map[string]interface{}) |
|
|
|
|
} else { |
|
|
|
|
dsDTO.JSONData = ds.JsonData.MustMap() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Access == models.DS_ACCESS_DIRECT { |
|
|
|
|
if ds.BasicAuth { |
|
|
|
|
dsDTO.BasicAuth = util.GetBasicAuthHeader( |
|
|
|
|
ds.BasicAuthUser, |
|
|
|
|
hs.DataSourcesService.DecryptedBasicAuthPassword(ds), |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
if ds.WithCredentials { |
|
|
|
|
dsDTO.WithCredentials = ds.WithCredentials |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Type == models.DS_INFLUXDB_08 { |
|
|
|
|
dsDTO.Username = ds.User |
|
|
|
|
dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) |
|
|
|
|
dsDTO.URL = url + "/db/" + ds.Database |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Type == models.DS_INFLUXDB { |
|
|
|
|
dsDTO.Username = ds.User |
|
|
|
|
dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) |
|
|
|
|
dsDTO.URL = url |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ds.Type == models.DS_INFLUXDB) || (ds.Type == models.DS_ES) { |
|
|
|
|
dsDTO.Database = ds.Database |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ds.Type == models.DS_PROMETHEUS { |
|
|
|
|
// add unproxied server URL for link to Prometheus web UI
|
|
|
|
|
ds.JsonData.Set("directUrl", ds.Url) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dataSources[ds.Name] = dsDTO |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// add data sources that are built in (meaning they are not added via data sources page, nor have any entry in
|
|
|
|
|
// the datasource table)
|
|
|
|
|
for _, ds := range hs.pluginStore.Plugins(c.Req.Context(), plugins.DataSource) { |
|
|
|
|
if ds.BuiltIn { |
|
|
|
|
dto := plugins.DataSourceDTO{ |
|
|
|
|
Type: string(ds.Type), |
|
|
|
|
Name: ds.Name, |
|
|
|
|
JSONData: make(map[string]interface{}), |
|
|
|
|
PluginMeta: &plugins.PluginMetaDTO{ |
|
|
|
|
JSONData: ds.JSONData, |
|
|
|
|
Signature: ds.Signature, |
|
|
|
|
Module: ds.Module, |
|
|
|
|
BaseURL: ds.BaseURL, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
if ds.Name == grafanads.DatasourceName { |
|
|
|
|
dto.ID = grafanads.DatasourceID |
|
|
|
|
dto.UID = grafanads.DatasourceUID |
|
|
|
|
} |
|
|
|
|
dataSources[ds.Name] = dto |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return dataSources, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func getPanelSort(id string) int { |
|
|
|
|
sort := 100 |
|
|
|
|
switch id { |
|
|
|
@ -331,16 +342,6 @@ func getPanelSort(id string) int { |
|
|
|
|
return sort |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (hs *HTTPServer) GetFrontendSettings(c *models.ReqContext) { |
|
|
|
|
settings, err := hs.getFrontendSettingsMap(c) |
|
|
|
|
if err != nil { |
|
|
|
|
c.JsonApiErr(400, "Failed to get frontend settings", err) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c.JSON(200, settings) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// EnabledPlugins represents a mapping from plugin types (panel, data source, etc.) to plugin IDs to plugins
|
|
|
|
|
// For example ["panel"] -> ["piechart"] -> {pie chart plugin DTO}
|
|
|
|
|
type EnabledPlugins map[plugins.Type]map[string]plugins.PluginDTO |
|
|
|
@ -389,15 +390,15 @@ func (hs *HTTPServer) enabledPlugins(ctx context.Context, orgID int64) (EnabledP |
|
|
|
|
return ep, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*models.PluginSettingInfoDTO, error) { |
|
|
|
|
pluginSettings := make(map[string]*models.PluginSettingInfoDTO) |
|
|
|
|
func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*pluginsettings.DTO, error) { |
|
|
|
|
pluginSettings := make(map[string]*pluginsettings.DTO) |
|
|
|
|
|
|
|
|
|
// fill settings from database
|
|
|
|
|
if pss, err := hs.PluginSettings.GetPluginSettings(ctx, orgID); err != nil { |
|
|
|
|
if pss, err := hs.PluginSettings.GetPluginSettings(ctx, &pluginsettings.GetArgs{OrgID: orgID}); err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} else { |
|
|
|
|
for _, ps := range pss { |
|
|
|
|
pluginSettings[ps.PluginId] = ps |
|
|
|
|
pluginSettings[ps.PluginID] = ps |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -409,9 +410,9 @@ func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[stri |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// add new setting which is enabled depending on if AutoEnabled: true
|
|
|
|
|
pluginSetting := &models.PluginSettingInfoDTO{ |
|
|
|
|
PluginId: plugin.ID, |
|
|
|
|
OrgId: orgID, |
|
|
|
|
pluginSetting := &pluginsettings.DTO{ |
|
|
|
|
PluginID: plugin.ID, |
|
|
|
|
OrgID: orgID, |
|
|
|
|
Enabled: plugin.AutoEnabled, |
|
|
|
|
Pinned: plugin.AutoEnabled, |
|
|
|
|
} |
|
|
|
@ -427,9 +428,9 @@ func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[stri |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// add new setting which is enabled by default
|
|
|
|
|
pluginSetting := &models.PluginSettingInfoDTO{ |
|
|
|
|
PluginId: plugin.ID, |
|
|
|
|
OrgId: orgID, |
|
|
|
|
pluginSetting := &pluginsettings.DTO{ |
|
|
|
|
PluginID: plugin.ID, |
|
|
|
|
OrgID: orgID, |
|
|
|
|
Enabled: true, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|