Plugins: Add typed models for frontend settings data sources and panels (#42062)

* add model for data source

* add model for panels

* add omitempty

* make consistent with main

* dont emit bools

* resolve conflicts

* remove file

* remove file

* update field name

* always pass jsonData

* minify the changes

* remove dupe line
This commit is contained in:
Will Browne 2021-12-14 10:16:13 +00:00 committed by GitHub
parent 6c4555265a
commit 155487bfb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 63 deletions

View File

@ -6,7 +6,6 @@ import (
"strconv"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/accesscontrol"
@ -15,12 +14,7 @@ import (
"github.com/grafana/grafana/pkg/util"
)
type PreloadPlugin struct {
Path string `json:"path"`
Version string `json:"version"`
}
func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]interface{}, error) {
func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]plugins.DataSourceDTO, error) {
orgDataSources := make([]*models.DataSource, 0)
if c.OrgId != 0 {
@ -47,7 +41,7 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
}
}
dataSources := make(map[string]interface{})
dataSources := make(map[string]plugins.DataSourceDTO)
for _, ds := range orgDataSources {
url := ds.Url
@ -56,81 +50,81 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10)
}
dsMap := map[string]interface{}{
"id": ds.Id,
"uid": ds.Uid,
"type": ds.Type,
"name": ds.Name,
"url": url,
"isDefault": ds.IsDefault,
"access": ds.Access,
dsDTO := plugins.DataSourceDTO{
ID: ds.Id,
UID: ds.Uid,
Type: ds.Type,
Name: ds.Name,
URL: url,
IsDefault: ds.IsDefault,
Access: string(ds.Access),
}
meta, exists := enabledPlugins.Get(plugins.DataSource, ds.Type)
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
}
dsMap["preload"] = meta.Preload
dsMap["module"] = meta.Module
dsMap["meta"] = &plugins.PluginMetaDTO{
JSONData: meta.JSONData,
Signature: meta.Signature,
Module: meta.Module,
BaseURL: meta.BaseURL,
dsDTO.Preload = plugin.Preload
dsDTO.Module = plugin.Module
dsDTO.PluginMeta = &plugins.PluginMetaDTO{
JSONData: plugin.JSONData,
Signature: plugin.Signature,
Module: plugin.Module,
BaseURL: plugin.BaseURL,
}
jsonData := ds.JsonData
if jsonData == nil {
jsonData = simplejson.New()
if ds.JsonData == nil {
dsDTO.JSONData = make(map[string]interface{})
} else {
dsDTO.JSONData = ds.JsonData.MustMap()
}
dsMap["jsonData"] = jsonData
if ds.Access == models.DS_ACCESS_DIRECT {
if ds.BasicAuth {
dsMap["basicAuth"] = util.GetBasicAuthHeader(
dsDTO.BasicAuth = util.GetBasicAuthHeader(
ds.BasicAuthUser,
hs.DataSourcesService.DecryptedBasicAuthPassword(ds),
)
}
if ds.WithCredentials {
dsMap["withCredentials"] = ds.WithCredentials
dsDTO.WithCredentials = ds.WithCredentials
}
if ds.Type == models.DS_INFLUXDB_08 {
dsMap["username"] = ds.User
dsMap["password"] = hs.DataSourcesService.DecryptedPassword(ds)
dsMap["url"] = url + "/db/" + ds.Database
dsDTO.Username = ds.User
dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds)
dsDTO.URL = url + "/db/" + ds.Database
}
if ds.Type == models.DS_INFLUXDB {
dsMap["username"] = ds.User
dsMap["password"] = hs.DataSourcesService.DecryptedPassword(ds)
dsMap["url"] = url
dsDTO.Username = ds.User
dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds)
dsDTO.URL = url
}
}
if (ds.Type == models.DS_INFLUXDB) || (ds.Type == models.DS_ES) {
dsMap["database"] = ds.Database
dsDTO.Database = ds.Database
}
if ds.Type == models.DS_PROMETHEUS {
// add unproxied server URL for link to Prometheus web UI
jsonData.Set("directUrl", ds.Url)
ds.JsonData.Set("directUrl", ds.Url)
}
dataSources[ds.Name] = dsMap
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 {
info := map[string]interface{}{
"type": ds.Type,
"name": ds.Name,
"meta": &plugins.PluginMetaDTO{
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,
@ -138,10 +132,10 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
},
}
if ds.Name == grafanads.DatasourceName {
info["id"] = grafanads.DatasourceID
info["uid"] = grafanads.DatasourceUID
dto.ID = grafanads.DatasourceID
dto.UID = grafanads.DatasourceUID
}
dataSources[ds.Name] = info
dataSources[ds.Name] = dto
}
}
@ -155,10 +149,10 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
return nil, err
}
pluginsToPreload := make([]*PreloadPlugin, 0)
pluginsToPreload := make([]*plugins.PreloadPlugin, 0)
for _, app := range enabledPlugins[plugins.App] {
if app.Preload {
pluginsToPreload = append(pluginsToPreload, &PreloadPlugin{
pluginsToPreload = append(pluginsToPreload, &plugins.PreloadPlugin{
Path: app.Module,
Version: app.Info.Version,
})
@ -172,29 +166,28 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
defaultDS := "-- Grafana --"
for n, ds := range dataSources {
dsM := ds.(map[string]interface{})
if isDefault, _ := dsM["isDefault"].(bool); isDefault {
if ds.IsDefault {
defaultDS = n
}
}
panels := map[string]interface{}{}
panels := make(map[string]plugins.PanelDTO)
for _, panel := range enabledPlugins[plugins.Panel] {
if panel.State == plugins.AlphaRelease && !hs.Cfg.PluginsEnableAlpha {
continue
}
panels[panel.ID] = map[string]interface{}{
"id": panel.ID,
"module": panel.Module,
"baseUrl": panel.BaseURL,
"name": panel.Name,
"info": panel.Info,
"hideFromList": panel.HideFromList,
"sort": getPanelSort(panel.ID),
"skipDataQuery": panel.SkipDataQuery,
"state": panel.State,
"signature": panel.Signature,
panels[panel.ID] = plugins.PanelDTO{
ID: panel.ID,
Name: panel.Name,
Info: panel.Info,
Module: panel.Module,
BaseURL: panel.BaseURL,
SkipDataQuery: panel.SkipDataQuery,
HideFromList: panel.HideFromList,
ReleaseState: string(panel.State),
Signature: string(panel.Signature),
Sort: getPanelSort(panel.ID),
}
}

View File

@ -199,6 +199,46 @@ type PluginMetaDTO struct {
BaseURL string `json:"baseUrl"`
}
type DataSourceDTO struct {
ID int64 `json:"id,omitempty"`
UID string `json:"uid,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
PluginMeta *PluginMetaDTO `json:"meta"`
URL string `json:"url,omitempty"`
IsDefault bool `json:"isDefault"`
Access string `json:"access,omitempty"`
Preload bool `json:"preload"`
Module string `json:"module,omitempty"`
JSONData map[string]interface{} `json:"jsonData"`
BasicAuth string `json:"basicAuth,omitempty"`
WithCredentials bool `json:"withCredentials,omitempty"`
// InfluxDB
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
// InfluxDB + Elasticsearch
Database string `json:"database,omitempty"`
// Prometheus
DirectURL string `json:"directUrl,omitempty"`
}
type PanelDTO struct {
ID string `json:"id"`
Name string `json:"name"`
Info Info `json:"info"`
HideFromList bool `json:"hideFromList"`
Sort int `json:"sort"`
SkipDataQuery bool `json:"skipDataQuery"`
ReleaseState string `json:"state"`
BaseURL string `json:"baseUrl"`
Signature string `json:"signature"`
Module string `json:"module"`
}
const (
signatureMissing ErrorCode = "signatureMissing"
signatureModified ErrorCode = "signatureModified"
@ -211,3 +251,8 @@ type Error struct {
ErrorCode `json:"errorCode"`
PluginID string `json:"pluginId,omitempty"`
}
type PreloadPlugin struct {
Path string `json:"path"`
Version string `json:"version"`
}