mirror of https://github.com/grafana/grafana
Backend Plugins: Plugin configuration using Grafana config (#23451)
Enables adding a section `plugin.<plugin id>` and key/value to Grafana configuration file which will be converted and sent as environment variables to the backend plugin. Also sends some additional environment variables, Grafana version (GF_VERSION), Grafana edition (GF_EDITION) and enterprise license path (GF_ENTERPRISE_LICENSE_PATH). Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Fixes #21515,pull/23543/head^2
parent
941cd59894
commit
34266cd369
@ -0,0 +1,39 @@ |
||||
package backendplugin |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strings" |
||||
|
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
type pluginSettings map[string]string |
||||
|
||||
func (ps pluginSettings) ToEnv(prefix string, hostEnv []string) []string { |
||||
env := []string{} |
||||
for k, v := range ps { |
||||
env = append(env, fmt.Sprintf("%s_%s=%s", prefix, strings.ToUpper(k), v)) |
||||
} |
||||
|
||||
env = append(env, hostEnv...) |
||||
|
||||
return env |
||||
} |
||||
|
||||
func extractPluginSettings(cfg *setting.Cfg) map[string]pluginSettings { |
||||
psMap := map[string]pluginSettings{} |
||||
for pluginID, settings := range cfg.PluginSettings { |
||||
ps := pluginSettings{} |
||||
for k, v := range settings { |
||||
if k == "path" || strings.ToLower(k) == "id" { |
||||
continue |
||||
} |
||||
|
||||
ps[k] = v |
||||
} |
||||
|
||||
psMap[pluginID] = ps |
||||
} |
||||
|
||||
return psMap |
||||
} |
@ -0,0 +1,46 @@ |
||||
package backendplugin |
||||
|
||||
import ( |
||||
"sort" |
||||
"testing" |
||||
|
||||
"github.com/grafana/grafana/pkg/setting" |
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func TestPluginSettings(t *testing.T) { |
||||
t.Run("Should only extract from sections beginning with 'plugin.' in config", func(t *testing.T) { |
||||
cfg := &setting.Cfg{ |
||||
PluginSettings: setting.PluginSettings{ |
||||
"plugin": map[string]string{ |
||||
"key1": "value1", |
||||
"key2": "value2", |
||||
}, |
||||
}, |
||||
} |
||||
|
||||
ps := extractPluginSettings(cfg) |
||||
require.Len(t, ps, 1) |
||||
require.Len(t, ps["plugin"], 2) |
||||
|
||||
t.Run("Should skip path setting", func(t *testing.T) { |
||||
cfg.PluginSettings["plugin"]["path"] = "value" |
||||
ps := extractPluginSettings(cfg) |
||||
require.Len(t, ps["plugin"], 2) |
||||
}) |
||||
|
||||
t.Run("Should skip id setting", func(t *testing.T) { |
||||
cfg.PluginSettings["plugin"]["id"] = "value" |
||||
ps := extractPluginSettings(cfg) |
||||
require.Len(t, ps["plugin"], 2) |
||||
}) |
||||
|
||||
t.Run("Should return expected environment variables from plugin settings ", func(t *testing.T) { |
||||
ps := extractPluginSettings(cfg) |
||||
env := ps["plugin"].ToEnv("GF_PLUGIN", []string{"GF_VERSION=6.7.0"}) |
||||
sort.Strings(env) |
||||
require.Len(t, env, 3) |
||||
require.EqualValues(t, []string{"GF_PLUGIN_KEY1=value1", "GF_PLUGIN_KEY2=value2", "GF_VERSION=6.7.0"}, env) |
||||
}) |
||||
}) |
||||
} |
@ -0,0 +1,25 @@ |
||||
package setting |
||||
|
||||
import ( |
||||
"strings" |
||||
|
||||
"gopkg.in/ini.v1" |
||||
) |
||||
|
||||
// PluginSettings maps plugin id to map of key/value settings.
|
||||
type PluginSettings map[string]map[string]string |
||||
|
||||
func extractPluginSettings(sections []*ini.Section) PluginSettings { |
||||
psMap := PluginSettings{} |
||||
for _, section := range sections { |
||||
sectionName := section.Name() |
||||
if !strings.HasPrefix(sectionName, "plugin.") { |
||||
continue |
||||
} |
||||
|
||||
pluginID := strings.Replace(sectionName, "plugin.", "", 1) |
||||
psMap[pluginID] = section.KeysHash() |
||||
} |
||||
|
||||
return psMap |
||||
} |
@ -0,0 +1,43 @@ |
||||
package setting |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func TestPluginSettings(t *testing.T) { |
||||
cfg := NewCfg() |
||||
sec, err := cfg.Raw.NewSection("plugin") |
||||
require.NoError(t, err) |
||||
_, err = sec.NewKey("key", "value") |
||||
require.NoError(t, err) |
||||
|
||||
sec, err = cfg.Raw.NewSection("plugin.plugin") |
||||
require.NoError(t, err) |
||||
_, err = sec.NewKey("key1", "value1") |
||||
require.NoError(t, err) |
||||
_, err = sec.NewKey("key2", "value2") |
||||
require.NoError(t, err) |
||||
|
||||
sec, err = cfg.Raw.NewSection("plugin.plugin2") |
||||
require.NoError(t, err) |
||||
_, err = sec.NewKey("key3", "value3") |
||||
require.NoError(t, err) |
||||
_, err = sec.NewKey("key4", "value4") |
||||
require.NoError(t, err) |
||||
|
||||
sec, err = cfg.Raw.NewSection("other") |
||||
require.NoError(t, err) |
||||
_, err = sec.NewKey("keySomething", "whatever") |
||||
require.NoError(t, err) |
||||
|
||||
ps := extractPluginSettings(cfg.Raw.Sections()) |
||||
require.Len(t, ps, 2) |
||||
require.Len(t, ps["plugin"], 2) |
||||
require.Equal(t, ps["plugin"]["key1"], "value1") |
||||
require.Equal(t, ps["plugin"]["key2"], "value2") |
||||
require.Len(t, ps["plugin2"], 2) |
||||
require.Equal(t, ps["plugin2"]["key3"], "value3") |
||||
require.Equal(t, ps["plugin2"]["key4"], "value4") |
||||
} |
Loading…
Reference in new issue