mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 12:23:10 +08:00
Feature: Allow to skip plugin loading (#74840)
This commit is contained in:

committed by
GitHub

parent
05f01dee0c
commit
96b55ea37c
@ -1478,6 +1478,8 @@ public_key_retrieval_disabled = false
|
|||||||
# Force download of the public key for verifying plugin signature on startup. If disabled, the public key will be retrieved every 10 days.
|
# Force download of the public key for verifying plugin signature on startup. If disabled, the public key will be retrieved every 10 days.
|
||||||
# Requires public_key_retrieval_disabled to be false to have any effect.
|
# Requires public_key_retrieval_disabled to be false to have any effect.
|
||||||
public_key_retrieval_on_startup = false
|
public_key_retrieval_on_startup = false
|
||||||
|
# Enter a comma-separated list of plugin identifiers to avoid loading (including core plugins). These plugins will be hidden in the catalog.
|
||||||
|
disable_plugins =
|
||||||
|
|
||||||
#################################### Grafana Live ##########################################
|
#################################### Grafana Live ##########################################
|
||||||
[live]
|
[live]
|
||||||
|
@ -1372,6 +1372,8 @@
|
|||||||
# Force download of the public key for verifying plugin signature on startup. If disabled, the public key will be retrieved every 10 days.
|
# Force download of the public key for verifying plugin signature on startup. If disabled, the public key will be retrieved every 10 days.
|
||||||
# Requires public_key_retrieval_disabled to be false to have any effect.
|
# Requires public_key_retrieval_disabled to be false to have any effect.
|
||||||
; public_key_retrieval_on_startup = false
|
; public_key_retrieval_on_startup = false
|
||||||
|
# Enter a comma-separated list of plugin identifiers to avoid loading (including core plugins). These plugins will be hidden in the catalog.
|
||||||
|
; disable_plugins =
|
||||||
|
|
||||||
#################################### Grafana Live ##########################################
|
#################################### Grafana Live ##########################################
|
||||||
[live]
|
[live]
|
||||||
|
@ -2112,6 +2112,10 @@ Disable download of the public key for verifying plugin signature. The default i
|
|||||||
|
|
||||||
Force download of the public key for verifying plugin signature on startup. The default is `false`. If disabled, the public key will be retrieved every 10 days. Requires `public_key_retrieval_disabled` to be false to have any effect.
|
Force download of the public key for verifying plugin signature on startup. The default is `false`. If disabled, the public key will be retrieved every 10 days. Requires `public_key_retrieval_disabled` to be false to have any effect.
|
||||||
|
|
||||||
|
### disable_plugins
|
||||||
|
|
||||||
|
Enter a comma-separated list of plugin identifiers to avoid loading (including core plugins). These plugins will be hidden in the catalog.
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
## [live]
|
## [live]
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package backendplugin
|
package backendplugin
|
||||||
|
|
||||||
import (
|
import "errors"
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrPluginNotRegistered error returned when plugin is not registered.
|
// ErrPluginNotRegistered error returned when plugin is not registered.
|
||||||
|
@ -17,6 +17,7 @@ type Cfg struct {
|
|||||||
|
|
||||||
PluginSettings setting.PluginSettings
|
PluginSettings setting.PluginSettings
|
||||||
PluginsAllowUnsigned []string
|
PluginsAllowUnsigned []string
|
||||||
|
DisablePlugins []string
|
||||||
|
|
||||||
// AWS Plugin Auth
|
// AWS Plugin Auth
|
||||||
AWSAllowedAuthProviders []string
|
AWSAllowedAuthProviders []string
|
||||||
@ -50,7 +51,7 @@ type Cfg struct {
|
|||||||
func NewCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string,
|
func NewCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string,
|
||||||
awsAllowedAuthProviders []string, awsAssumeRoleEnabled bool, awsExternalId string, azure *azsettings.AzureSettings, secureSocksDSProxy setting.SecureSocksDSProxySettings,
|
awsAllowedAuthProviders []string, awsAssumeRoleEnabled bool, awsExternalId string, azure *azsettings.AzureSettings, secureSocksDSProxy setting.SecureSocksDSProxySettings,
|
||||||
grafanaVersion string, logDatasourceRequests bool, pluginsCDNURLTemplate string, appURL string, appSubURL string, tracing Tracing, features plugins.FeatureToggles, angularSupportEnabled bool,
|
grafanaVersion string, logDatasourceRequests bool, pluginsCDNURLTemplate string, appURL string, appSubURL string, tracing Tracing, features plugins.FeatureToggles, angularSupportEnabled bool,
|
||||||
grafanaComURL string) *Cfg {
|
grafanaComURL string, disablePlugins []string) *Cfg {
|
||||||
return &Cfg{
|
return &Cfg{
|
||||||
log: log.New("plugin.cfg"),
|
log: log.New("plugin.cfg"),
|
||||||
PluginsPath: pluginsPath,
|
PluginsPath: pluginsPath,
|
||||||
@ -58,6 +59,7 @@ func NewCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSetti
|
|||||||
DevMode: devMode,
|
DevMode: devMode,
|
||||||
PluginSettings: pluginSettings,
|
PluginSettings: pluginSettings,
|
||||||
PluginsAllowUnsigned: pluginsAllowUnsigned,
|
PluginsAllowUnsigned: pluginsAllowUnsigned,
|
||||||
|
DisablePlugins: disablePlugins,
|
||||||
AWSAllowedAuthProviders: awsAllowedAuthProviders,
|
AWSAllowedAuthProviders: awsAllowedAuthProviders,
|
||||||
AWSAssumeRoleEnabled: awsAssumeRoleEnabled,
|
AWSAssumeRoleEnabled: awsAssumeRoleEnabled,
|
||||||
AWSExternalId: awsExternalId,
|
AWSExternalId: awsExternalId,
|
||||||
|
@ -46,6 +46,7 @@ func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg, fe
|
|||||||
features,
|
features,
|
||||||
grafanaCfg.AngularSupportEnabled,
|
grafanaCfg.AngularSupportEnabled,
|
||||||
grafanaCfg.GrafanaComURL,
|
grafanaCfg.GrafanaComURL,
|
||||||
|
grafanaCfg.DisablePlugins,
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ func ProvideDiscoveryStage(cfg *config.Cfg, pf finder.Finder, pr registry.Servic
|
|||||||
func(ctx context.Context, _ plugins.Class, b []*plugins.FoundBundle) ([]*plugins.FoundBundle, error) {
|
func(ctx context.Context, _ plugins.Class, b []*plugins.FoundBundle) ([]*plugins.FoundBundle, error) {
|
||||||
return discovery.NewDuplicatePluginFilterStep(pr).Filter(ctx, b)
|
return discovery.NewDuplicatePluginFilterStep(pr).Filter(ctx, b)
|
||||||
},
|
},
|
||||||
|
func(_ context.Context, _ plugins.Class, b []*plugins.FoundBundle) ([]*plugins.FoundBundle, error) {
|
||||||
|
return NewDisablePluginsStep(cfg).Filter(b)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -121,3 +121,39 @@ func (v *SignatureValidation) Validate(ctx context.Context, p *plugins.Plugin) e
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisablePlugins is a filter step that will filter out any configured plugins
|
||||||
|
type DisablePlugins struct {
|
||||||
|
log log.Logger
|
||||||
|
cfg *config.Cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDisablePluginsStep returns a new DisablePlugins.
|
||||||
|
func NewDisablePluginsStep(cfg *config.Cfg) *DisablePlugins {
|
||||||
|
return &DisablePlugins{
|
||||||
|
cfg: cfg,
|
||||||
|
log: log.New("plugins.disable"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter will filter out any plugins that are marked to be disabled.
|
||||||
|
func (c *DisablePlugins) Filter(bundles []*plugins.FoundBundle) ([]*plugins.FoundBundle, error) {
|
||||||
|
if len(c.cfg.DisablePlugins) == 0 {
|
||||||
|
return bundles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
disablePluginsMap := make(map[string]bool)
|
||||||
|
for _, pluginID := range c.cfg.DisablePlugins {
|
||||||
|
disablePluginsMap[pluginID] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
res := []*plugins.FoundBundle{}
|
||||||
|
for _, bundle := range bundles {
|
||||||
|
if disablePluginsMap[bundle.Primary.JSONData.ID] {
|
||||||
|
c.log.Debug("Disabling plugin load", "pluginID", bundle.Primary.JSONData.ID)
|
||||||
|
} else {
|
||||||
|
res = append(res, bundle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
45
pkg/services/pluginsintegration/pipeline/steps_test.go
Normal file
45
pkg/services/pluginsintegration/pipeline/steps_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package pipeline
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/config"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSkipPlugins(t *testing.T) {
|
||||||
|
cfg := &config.Cfg{
|
||||||
|
DisablePlugins: []string{"plugin1", "plugin2"},
|
||||||
|
}
|
||||||
|
s := NewDisablePluginsStep(cfg)
|
||||||
|
|
||||||
|
bundles := []*plugins.FoundBundle{
|
||||||
|
{
|
||||||
|
Primary: plugins.FoundPlugin{
|
||||||
|
JSONData: plugins.JSONData{
|
||||||
|
ID: "plugin1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Primary: plugins.FoundPlugin{
|
||||||
|
JSONData: plugins.JSONData{
|
||||||
|
ID: "plugin2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Primary: plugins.FoundPlugin{
|
||||||
|
JSONData: plugins.JSONData{
|
||||||
|
ID: "plugin3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered, err := s.Filter(bundles)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, filtered, 1)
|
||||||
|
require.Equal(t, filtered[0].Primary.JSONData.ID, "plugin3")
|
||||||
|
}
|
@ -243,6 +243,7 @@ type Cfg struct {
|
|||||||
PluginAdminExternalManageEnabled bool
|
PluginAdminExternalManageEnabled bool
|
||||||
PluginForcePublicKeyDownload bool
|
PluginForcePublicKeyDownload bool
|
||||||
PluginSkipPublicKeyDownload bool
|
PluginSkipPublicKeyDownload bool
|
||||||
|
DisablePlugins []string
|
||||||
|
|
||||||
PluginsCDNURLTemplate string
|
PluginsCDNURLTemplate string
|
||||||
PluginLogBackendRequests bool
|
PluginLogBackendRequests bool
|
||||||
|
@ -40,6 +40,14 @@ func (cfg *Cfg) readPluginSettings(iniFile *ini.File) error {
|
|||||||
cfg.PluginsAllowUnsigned = append(cfg.PluginsAllowUnsigned, plug)
|
cfg.PluginsAllowUnsigned = append(cfg.PluginsAllowUnsigned, plug)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disablePlugins := pluginsSection.Key("disable_plugins").MustString("")
|
||||||
|
for _, plug := range strings.Split(disablePlugins, ",") {
|
||||||
|
plug = strings.TrimSpace(plug)
|
||||||
|
if plug != "" {
|
||||||
|
cfg.DisablePlugins = append(cfg.DisablePlugins, plug)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cfg.PluginCatalogURL = pluginsSection.Key("plugin_catalog_url").MustString("https://grafana.com/grafana/plugins/")
|
cfg.PluginCatalogURL = pluginsSection.Key("plugin_catalog_url").MustString("https://grafana.com/grafana/plugins/")
|
||||||
cfg.PluginAdminEnabled = pluginsSection.Key("plugin_admin_enabled").MustBool(true)
|
cfg.PluginAdminEnabled = pluginsSection.Key("plugin_admin_enabled").MustBool(true)
|
||||||
cfg.PluginAdminExternalManageEnabled = pluginsSection.Key("plugin_admin_external_manage_enabled").MustBool(false)
|
cfg.PluginAdminExternalManageEnabled = pluginsSection.Key("plugin_admin_external_manage_enabled").MustBool(false)
|
||||||
@ -49,6 +57,8 @@ func (cfg *Cfg) readPluginSettings(iniFile *ini.File) error {
|
|||||||
plug = strings.TrimSpace(plug)
|
plug = strings.TrimSpace(plug)
|
||||||
cfg.PluginCatalogHiddenPlugins = append(cfg.PluginCatalogHiddenPlugins, plug)
|
cfg.PluginCatalogHiddenPlugins = append(cfg.PluginCatalogHiddenPlugins, plug)
|
||||||
}
|
}
|
||||||
|
// Pull disablep plugins from the catalog
|
||||||
|
cfg.PluginCatalogHiddenPlugins = append(cfg.PluginCatalogHiddenPlugins, cfg.DisablePlugins...)
|
||||||
|
|
||||||
// Plugins CDN settings
|
// Plugins CDN settings
|
||||||
cfg.PluginsCDNURLTemplate = strings.TrimRight(pluginsSection.Key("cdn_base_url").MustString(""), "/")
|
cfg.PluginsCDNURLTemplate = strings.TrimRight(pluginsSection.Key("cdn_base_url").MustString(""), "/")
|
||||||
|
@ -41,3 +41,20 @@ func TestPluginSettings(t *testing.T) {
|
|||||||
require.Equal(t, ps["plugin2"]["key3"], "value3")
|
require.Equal(t, ps["plugin2"]["key3"], "value3")
|
||||||
require.Equal(t, ps["plugin2"]["key4"], "value4")
|
require.Equal(t, ps["plugin2"]["key4"], "value4")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_readPluginSettings(t *testing.T) {
|
||||||
|
t.Run("should parse disable_plugins", func(t *testing.T) {
|
||||||
|
cfg := NewCfg()
|
||||||
|
sec, err := cfg.Raw.NewSection("plugins")
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = sec.NewKey("disable_plugins", "plugin1,plugin2")
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = sec.NewKey("plugin_catalog_hidden_plugins", "plugin3")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = cfg.readPluginSettings(cfg.Raw)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []string{"plugin1", "plugin2"}, cfg.DisablePlugins)
|
||||||
|
require.Equal(t, []string{"plugin3", "plugin1", "plugin2"}, cfg.PluginCatalogHiddenPlugins)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user