mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 03:22:24 +08:00
419 lines
13 KiB
Go
419 lines
13 KiB
Go
package setting
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"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")
|
|
}
|
|
|
|
func Test_readPluginSettings(t *testing.T) {
|
|
t.Run("should parse separated plugin ids", func(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
f func(ids ...string) string
|
|
}{
|
|
{
|
|
name: "commas",
|
|
f: func(ids ...string) string {
|
|
return strings.Join(ids, ",")
|
|
},
|
|
},
|
|
{
|
|
name: "commas and a space",
|
|
f: func(ids ...string) string {
|
|
return strings.Join(ids, ", ")
|
|
},
|
|
},
|
|
{
|
|
name: "spaces",
|
|
f: func(ids ...string) string {
|
|
return strings.Join(ids, " ")
|
|
},
|
|
},
|
|
{
|
|
name: "json-like",
|
|
f: func(ids ...string) string {
|
|
return `["` + strings.Join(ids, `","`) + `"]`
|
|
},
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cfg := NewCfg()
|
|
sec, err := cfg.Raw.NewSection("plugins")
|
|
require.NoError(t, err)
|
|
_, err = sec.NewKey("disable_plugins", tc.f("plugin1", "plugin2"))
|
|
require.NoError(t, err)
|
|
|
|
_, err = sec.NewKey("plugin_catalog_hidden_plugins", tc.f("plugin3"))
|
|
require.NoError(t, err)
|
|
|
|
_, err = sec.NewKey("hide_angular_deprecation", tc.f("a", "b", "c"))
|
|
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)
|
|
require.Equal(t, []string{"a", "b", "c"}, cfg.HideAngularDeprecation)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("when plugins.preinstall_sync is defined", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
rawInput string
|
|
expected []InstallPlugin
|
|
disablePlugins string
|
|
disablePreinstall bool
|
|
}{
|
|
{
|
|
name: "should add the plugin to the sync list - not contain default plugins like async list",
|
|
rawInput: "plugin1",
|
|
expected: []InstallPlugin{
|
|
{ID: "plugin1", Version: "", URL: ""},
|
|
},
|
|
},
|
|
{
|
|
name: "it should remove the disabled plugin",
|
|
rawInput: "plugin1,plugin2",
|
|
disablePlugins: "plugin1",
|
|
expected: []InstallPlugin{{ID: "plugin2"}},
|
|
},
|
|
{
|
|
name: "should not process at all when preinstall is disabled",
|
|
rawInput: "plugin1",
|
|
disablePreinstall: true,
|
|
expected: nil,
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cfg := NewCfg()
|
|
sec, err := cfg.Raw.NewSection("plugins")
|
|
require.NoError(t, err)
|
|
_, err = sec.NewKey("preinstall_sync", tc.rawInput)
|
|
require.NoError(t, err)
|
|
if tc.disablePreinstall {
|
|
_, err = sec.NewKey("preinstall_disabled", "true")
|
|
require.NoError(t, err)
|
|
}
|
|
if tc.disablePlugins != "" {
|
|
_, err = sec.NewKey("disable_plugins", tc.disablePlugins)
|
|
require.NoError(t, err)
|
|
}
|
|
err = cfg.readPluginSettings(cfg.Raw)
|
|
require.NoError(t, err)
|
|
assert.ElementsMatch(t, cfg.PreinstallPluginsSync, tc.expected)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("when plugins.preinstall is defined", func(t *testing.T) {
|
|
defaultPreinstallPluginsList := make([]InstallPlugin, 0, len(defaultPreinstallPlugins))
|
|
defaultPreinstallPluginsIDs := []string{}
|
|
for _, p := range defaultPreinstallPlugins {
|
|
defaultPreinstallPluginsList = append(defaultPreinstallPluginsList, p)
|
|
defaultPreinstallPluginsIDs = append(defaultPreinstallPluginsIDs, p.ID)
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
rawInput string
|
|
rawInputSync string
|
|
disablePreinstall bool
|
|
expected []InstallPlugin
|
|
expectedSync []InstallPlugin
|
|
disableAsync bool
|
|
disablePlugins string
|
|
}{
|
|
{
|
|
name: "should add the default preinstalled plugin",
|
|
rawInput: "",
|
|
expected: defaultPreinstallPluginsList,
|
|
},
|
|
{
|
|
name: "should add the default preinstalled plugin and the one defined",
|
|
rawInput: "plugin1",
|
|
expected: append(defaultPreinstallPluginsList, InstallPlugin{ID: "plugin1", Version: "", URL: ""}),
|
|
},
|
|
{
|
|
name: "should add the default preinstalled plugin and the one defined with version",
|
|
rawInput: "plugin1@1.0.0",
|
|
expected: append(defaultPreinstallPluginsList, InstallPlugin{ID: "plugin1", Version: "1.0.0", URL: ""}),
|
|
},
|
|
{
|
|
name: "it should remove the disabled plugin",
|
|
rawInput: "plugin1",
|
|
disablePlugins: "plugin1",
|
|
expected: defaultPreinstallPluginsList,
|
|
},
|
|
{
|
|
name: "it should remove default plugins",
|
|
rawInput: "",
|
|
disablePlugins: strings.Join(defaultPreinstallPluginsIDs, ","),
|
|
expected: nil,
|
|
},
|
|
{
|
|
name: "should ignore input when preinstall is disabled",
|
|
rawInput: "plugin1",
|
|
disablePreinstall: true,
|
|
expected: nil,
|
|
},
|
|
{
|
|
name: "should mark preinstall as sync",
|
|
rawInput: "plugin1",
|
|
disableAsync: true,
|
|
expected: nil,
|
|
expectedSync: append(defaultPreinstallPluginsList, InstallPlugin{"plugin1", "", ""}),
|
|
},
|
|
{
|
|
name: "should parse a plugin with version and URL",
|
|
rawInput: "plugin1@1.0.1@https://example.com/plugin1.tar.gz",
|
|
expected: append(defaultPreinstallPluginsList, InstallPlugin{ID: "plugin1", Version: "1.0.1", URL: "https://example.com/plugin1.tar.gz"}),
|
|
},
|
|
{
|
|
name: "should parse a plugin with URL",
|
|
rawInput: "plugin1@@https://example.com/plugin1.tar.gz",
|
|
expected: append(defaultPreinstallPluginsList, InstallPlugin{ID: "plugin1", Version: "", URL: "https://example.com/plugin1.tar.gz"}),
|
|
},
|
|
{
|
|
name: "when preinstall_async is false, should add all plugins to preinstall_sync",
|
|
rawInput: "plugin1",
|
|
rawInputSync: "plugin2",
|
|
disableAsync: true,
|
|
expected: nil,
|
|
expectedSync: append(defaultPreinstallPluginsList, InstallPlugin{"plugin1", "", ""}, InstallPlugin{"plugin2", "", ""}),
|
|
},
|
|
{
|
|
name: "should overwrite default when user pins a version",
|
|
rawInput: "grafana-pyroscope-app@4.0.0",
|
|
expected: func() []InstallPlugin {
|
|
var plugins []InstallPlugin
|
|
for _, p := range defaultPreinstallPlugins {
|
|
if p.ID == "grafana-pyroscope-app" {
|
|
plugins = append(plugins, InstallPlugin{"grafana-pyroscope-app", "4.0.0", ""})
|
|
} else {
|
|
plugins = append(plugins, p)
|
|
}
|
|
}
|
|
return plugins
|
|
}(),
|
|
},
|
|
{
|
|
name: "when same plugin is defined in preinstall and preinstall_sync, should be only in preinstallSync",
|
|
rawInput: "plugin1",
|
|
rawInputSync: "plugin1",
|
|
expected: defaultPreinstallPluginsList,
|
|
expectedSync: []InstallPlugin{{ID: "plugin1"}},
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cfg := NewCfg()
|
|
sec, err := cfg.Raw.NewSection("plugins")
|
|
require.NoError(t, err)
|
|
_, err = sec.NewKey("preinstall", tc.rawInput)
|
|
require.NoError(t, err)
|
|
if tc.rawInputSync != "" {
|
|
_, err = sec.NewKey("preinstall_sync", tc.rawInputSync)
|
|
require.NoError(t, err)
|
|
}
|
|
if tc.disablePreinstall {
|
|
_, err = sec.NewKey("preinstall_disabled", "true")
|
|
require.NoError(t, err)
|
|
}
|
|
if tc.disableAsync {
|
|
_, err = sec.NewKey("preinstall_async", "false")
|
|
require.NoError(t, err)
|
|
}
|
|
if tc.disablePlugins != "" {
|
|
_, err = sec.NewKey("disable_plugins", tc.disablePlugins)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
err = cfg.readPluginSettings(cfg.Raw)
|
|
require.NoError(t, err)
|
|
assert.ElementsMatch(t, cfg.PreinstallPluginsAsync, tc.expected)
|
|
if tc.expectedSync != nil {
|
|
assert.ElementsMatch(t, cfg.PreinstallPluginsSync, tc.expectedSync)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
func Test_migrateInstallPluginsToPreinstallPluginsSync(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
installPluginsVal string
|
|
installPluginsForce string
|
|
preinstallPlugins map[string]InstallPlugin
|
|
expectedPlugins map[string]InstallPlugin
|
|
}{
|
|
{
|
|
name: "should return empty map when GF_INSTALL_PLUGINS is not set",
|
|
installPluginsVal: "",
|
|
preinstallPlugins: map[string]InstallPlugin{},
|
|
expectedPlugins: map[string]InstallPlugin{},
|
|
},
|
|
{
|
|
name: "should parse URL with folder format",
|
|
installPluginsVal: "https://grafana.com/grafana/plugins/grafana-piechart-panel/;grafana-piechart-panel",
|
|
preinstallPlugins: map[string]InstallPlugin{},
|
|
expectedPlugins: map[string]InstallPlugin{
|
|
"grafana-piechart-panel": {
|
|
ID: "grafana-piechart-panel",
|
|
Version: "",
|
|
URL: "https://grafana.com/grafana/plugins/grafana-piechart-panel/",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should parse mixed formats",
|
|
installPluginsVal: "https://github.com/VolkovLabs/business-links/releases/download/v1.2.1/volkovlabs-links-panel-1.2.1.zip;volkovlabs-links-panel,marcusolsson-static-datasource,volkovlabs-variable-panel",
|
|
preinstallPlugins: map[string]InstallPlugin{},
|
|
expectedPlugins: map[string]InstallPlugin{
|
|
"volkovlabs-links-panel": {
|
|
ID: "volkovlabs-links-panel",
|
|
Version: "",
|
|
URL: "https://github.com/VolkovLabs/business-links/releases/download/v1.2.1/volkovlabs-links-panel-1.2.1.zip",
|
|
},
|
|
"marcusolsson-static-datasource": {
|
|
ID: "marcusolsson-static-datasource",
|
|
Version: "",
|
|
URL: "",
|
|
},
|
|
"volkovlabs-variable-panel": {
|
|
ID: "volkovlabs-variable-panel",
|
|
Version: "",
|
|
URL: "",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should parse ID with version format",
|
|
installPluginsVal: "volkovlabs-links-panel 1.2.1,marcusolsson-static-datasource 1.0.0,volkovlabs-variable-panel",
|
|
preinstallPlugins: map[string]InstallPlugin{},
|
|
expectedPlugins: map[string]InstallPlugin{
|
|
"volkovlabs-links-panel": {
|
|
ID: "volkovlabs-links-panel",
|
|
Version: "1.2.1",
|
|
URL: "",
|
|
},
|
|
"marcusolsson-static-datasource": {
|
|
ID: "marcusolsson-static-datasource",
|
|
Version: "1.0.0",
|
|
URL: "",
|
|
},
|
|
"volkovlabs-variable-panel": {
|
|
ID: "volkovlabs-variable-panel",
|
|
Version: "",
|
|
URL: "",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should return empty map when GF_INSTALL_PLUGINS_FORCE is true",
|
|
installPluginsVal: "grafana-piechart-panel",
|
|
installPluginsForce: "true",
|
|
preinstallPlugins: map[string]InstallPlugin{},
|
|
expectedPlugins: map[string]InstallPlugin{},
|
|
},
|
|
{
|
|
name: "should skip plugins that are already configured",
|
|
installPluginsVal: "plugin1 1.0.0,plugin2,plugin3",
|
|
preinstallPlugins: map[string]InstallPlugin{
|
|
"plugin1": {ID: "plugin1", Version: "1.0.1"},
|
|
"plugin3": {ID: "plugin3"},
|
|
},
|
|
expectedPlugins: map[string]InstallPlugin{
|
|
"plugin2": {
|
|
ID: "plugin2",
|
|
},
|
|
"plugin3": {
|
|
ID: "plugin3",
|
|
},
|
|
"plugin1": {
|
|
ID: "plugin1",
|
|
Version: "1.0.1",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should trim the space in the input",
|
|
installPluginsVal: " plugin1 1.0.0, plugin2, plugin3 ",
|
|
preinstallPlugins: map[string]InstallPlugin{},
|
|
expectedPlugins: map[string]InstallPlugin{
|
|
"plugin2": {
|
|
ID: "plugin2",
|
|
},
|
|
"plugin3": {
|
|
ID: "plugin3",
|
|
},
|
|
"plugin1": {
|
|
ID: "plugin1",
|
|
Version: "1.0.0",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cfg := NewCfg()
|
|
|
|
cfg.migrateInstallPluginsToPreinstallPluginsSync(tc.installPluginsVal, tc.installPluginsForce, tc.preinstallPlugins)
|
|
assert.Equal(t, len(tc.expectedPlugins), len(tc.preinstallPlugins), "Number of plugins doesn't match")
|
|
|
|
// Check each expected plugin exists with correct values
|
|
for id, expectedPlugin := range tc.expectedPlugins {
|
|
actualPlugin, exists := tc.preinstallPlugins[id]
|
|
assert.True(t, exists, "Expected plugin %s not found", id)
|
|
if exists {
|
|
assert.Equal(t, expectedPlugin.ID, actualPlugin.ID, "Plugin ID mismatch for %s", id)
|
|
assert.Equal(t, expectedPlugin.Version, actualPlugin.Version, "Plugin version mismatch for %s", id)
|
|
assert.Equal(t, expectedPlugin.URL, actualPlugin.URL, "Plugin URL mismatch for %s", id)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|