Plugins: Set grafana config, plugin version and user agent on plugin requests (#75171)

* first pass

* fixup

* remove test line

* fix tests

* use new fields

* fix imports + formatting

* fix tests

* rollback changes

* undo whitespace

* apply pr feedback
This commit is contained in:
Will Browne
2023-09-21 11:33:31 +02:00
committed by GitHub
parent dd8f88b194
commit 7fca1bde54
37 changed files with 248 additions and 102 deletions
@@ -5,35 +5,54 @@ import (
"encoding/json"
"errors"
"fmt"
"runtime"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/useragent"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/envvars"
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/pluginsintegration/adapters"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/setting"
)
const (
pluginSettingsCacheTTL = 5 * time.Second
pluginSettingsCachePrefix = "plugin-setting-"
)
var ErrPluginNotFound = errors.New("plugin not found")
func ProvideService(cacheService *localcache.CacheService, pluginStore pluginstore.Store,
dataSourceService datasources.DataSourceService, pluginSettingsService pluginsettings.Service) *Provider {
func ProvideService(cfg *setting.Cfg, cacheService *localcache.CacheService, pluginStore pluginstore.Store,
dataSourceService datasources.DataSourceService, pluginSettingsService pluginsettings.Service,
licensing plugins.Licensing, pCfg *config.Cfg) *Provider {
return &Provider{
cfg: cfg,
cacheService: cacheService,
pluginStore: pluginStore,
dataSourceService: dataSourceService,
pluginSettingsService: pluginSettingsService,
pluginEnvVars: envvars.NewProvider(pCfg, licensing),
logger: log.New("plugin.context"),
}
}
type Provider struct {
cfg *setting.Cfg
pluginEnvVars *envvars.Service
cacheService *localcache.CacheService
pluginStore pluginstore.Store
dataSourceService datasources.DataSourceService
pluginSettingsService pluginsettings.Service
logger log.Logger
}
// Get allows getting plugin context by its ID. If datasourceUID is not empty string
@@ -47,7 +66,8 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user identity.Reque
}
pCtx := backend.PluginContext{
PluginID: pluginID,
PluginID: pluginID,
PluginVersion: plugin.Info.Version,
}
if user != nil && !user.IsNil() {
pCtx.OrgID = user.GetOrgID()
@@ -62,6 +82,12 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user identity.Reque
pCtx.AppInstanceSettings = appSettings
}
ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH)
if err != nil {
p.logger.Warn("Could not create user agent", "error", err)
}
pCtx.UserAgent = ua
return pCtx, nil
}
@@ -69,13 +95,14 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user identity.Reque
// resolved and appended to the returned context.
// Note: *user.SignedInUser can be nil.
func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error) {
_, exists := p.pluginStore.Plugin(ctx, pluginID)
plugin, exists := p.pluginStore.Plugin(ctx, pluginID)
if !exists {
return backend.PluginContext{}, ErrPluginNotFound
}
pCtx := backend.PluginContext{
PluginID: pluginID,
PluginID: pluginID,
PluginVersion: plugin.Info.Version,
}
if user != nil && !user.IsNil() {
pCtx.OrgID = user.GetOrgID()
@@ -88,12 +115,18 @@ func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user
}
pCtx.DataSourceInstanceSettings = datasourceSettings
settings := p.pluginEnvVars.GetConfigMap(ctx, pluginID, plugin.ExternalService)
pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings)
ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH)
if err != nil {
p.logger.Warn("Could not create user agent", "error", err)
}
pCtx.UserAgent = ua
return pCtx, nil
}
const pluginSettingsCacheTTL = 5 * time.Second
const pluginSettingsCachePrefix = "plugin-setting-"
func (p *Provider) appInstanceSettings(ctx context.Context, pluginID string, orgID int64) (*backend.AppInstanceSettings, error) {
jsonData := json.RawMessage{}
decryptedSecureJSONData := map[string]string{}
@@ -4,6 +4,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/oauth"
)
type Plugin struct {
@@ -32,7 +33,9 @@ type Plugin struct {
AngularDetected bool
// This will be moved to plugin.json when we have general support in gcom
Alias string `json:"alias,omitempty"`
Alias string
ExternalService *oauth.ExternalService
}
func (p Plugin) SupportsStreaming() bool {
@@ -74,5 +77,6 @@ func ToGrafanaDTO(p *plugins.Plugin) Plugin {
BaseURL: p.BaseURL,
AngularDetected: p.AngularDetected,
Alias: p.Alias,
ExternalService: p.ExternalService,
}
}
@@ -16,6 +16,8 @@ import (
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
@@ -119,15 +121,17 @@ func buildQueryDataService(t *testing.T, cs datasources.CacheService, fpc *fakeP
}
ds := &fakeDatasources.FakeDataSourceService{}
pCtxProvider := plugincontext.ProvideService(localcache.ProvideService(), &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "mysql",
pCtxProvider := plugincontext.ProvideService(setting.NewCfg(),
localcache.ProvideService(), &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "mysql",
},
},
},
},
}, ds, pluginSettings.ProvideService(store, fakeSecrets.NewFakeSecretsService()))
}, ds, pluginSettings.ProvideService(store, fakeSecrets.NewFakeSecretsService()), fakes.NewFakeLicensingService(),
&config.Cfg{})
return query.ProvideService(
setting.NewCfg(),
+4 -2
View File
@@ -24,6 +24,8 @@ import (
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models/roletype"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
pluginFakes "github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
@@ -467,7 +469,7 @@ func setup(t *testing.T) *testContext {
SimulatePluginFailure: false,
}
pCtxProvider := plugincontext.ProvideService(
pCtxProvider := plugincontext.ProvideService(sqlStore.Cfg,
localcache.ProvideService(), &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "postgres"}},
@@ -475,7 +477,7 @@ func setup(t *testing.T) *testContext {
{JSONData: plugins.JSONData{ID: "mysql"}},
},
}, fakeDatasourceService,
pluginSettings.ProvideService(sqlStore, secretsService),
pluginSettings.ProvideService(sqlStore, secretsService), pluginFakes.NewFakeLicensingService(), &config.Cfg{},
)
exprService := expr.ProvideService(&setting.Cfg{ExpressionsEnabled: true}, pc, pCtxProvider,
&featuremgmt.FeatureManager{}, nil, tracing.InitializeTracerForTest())