From 369d0a6aca77f9a497b45f6c05255195124917f4 Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Thu, 14 Nov 2024 13:36:57 +0100 Subject: [PATCH] Preinstall: Allow to extend default list (#96402) --- conf/defaults.ini | 3 +- pkg/setting/setting_plugins.go | 25 ++++++++- pkg/setting/setting_plugins_test.go | 86 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 4 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index 9b3184ebafa..ad60ca5f9a0 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -1756,7 +1756,8 @@ hide_angular_deprecation = # Comma separated list of plugin ids for which environment variables should be forwarded. Used only when feature flag pluginsSkipHostEnvVars is enabled. forward_host_env_vars = # Comma separated list of plugin ids to install as part of the startup process. -preinstall = grafana-lokiexplore-app +# By default, the following plugins will be preinstalled: "grafana-lokiexplore-app" +preinstall = # Controls whether preinstall plugins asynchronously (in the background) or synchronously (blocking). Useful when preinstalled plugins are used with provisioning. preinstall_async = true # Disables preinstall feature. It has the same effect as setting preinstall to an empty list. diff --git a/pkg/setting/setting_plugins.go b/pkg/setting/setting_plugins.go index 904dadcb20e..d3ba8384a40 100644 --- a/pkg/setting/setting_plugins.go +++ b/pkg/setting/setting_plugins.go @@ -26,6 +26,13 @@ func extractPluginSettings(sections []*ini.Section) PluginSettings { return psMap } +var ( + defaultPreinstallPlugins = map[string]InstallPlugin{ + // Default preinstalled plugins + "grafana-lokiexplore-app": {"grafana-lokiexplore-app", ""}, + } +) + func (cfg *Cfg) readPluginSettings(iniFile *ini.File) error { pluginsSection := iniFile.Section("plugins") @@ -42,15 +49,27 @@ func (cfg *Cfg) readPluginSettings(iniFile *ini.File) error { disablePreinstall := pluginsSection.Key("preinstall_disabled").MustBool(false) if !disablePreinstall { rawInstallPlugins := util.SplitString(pluginsSection.Key("preinstall").MustString("")) - cfg.PreinstallPlugins = make([]InstallPlugin, len(rawInstallPlugins)) - for i, plugin := range rawInstallPlugins { + preinstallPlugins := make(map[string]InstallPlugin) + // Add the default preinstalled plugins + for _, plugin := range defaultPreinstallPlugins { + preinstallPlugins[plugin.ID] = plugin + } + // Add the plugins defined in the configuration + for _, plugin := range rawInstallPlugins { parts := strings.Split(plugin, "@") id := parts[0] v := "" if len(parts) == 2 { v = parts[1] } - cfg.PreinstallPlugins[i] = InstallPlugin{id, v} + preinstallPlugins[id] = InstallPlugin{id, v} + } + // Remove from the list the plugins that have been disabled + for _, disabledPlugin := range cfg.DisablePlugins { + delete(preinstallPlugins, disabledPlugin) + } + for _, plugin := range preinstallPlugins { + cfg.PreinstallPlugins = append(cfg.PreinstallPlugins, plugin) } cfg.PreinstallPluginsAsync = pluginsSection.Key("preinstall_async").MustBool(true) } diff --git a/pkg/setting/setting_plugins_test.go b/pkg/setting/setting_plugins_test.go index 6ca5e0cc692..de1e45d9f42 100644 --- a/pkg/setting/setting_plugins_test.go +++ b/pkg/setting/setting_plugins_test.go @@ -4,6 +4,7 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -95,4 +96,89 @@ func Test_readPluginSettings(t *testing.T) { }) } }) + + 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 + disablePreinstall bool + expected []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{"plugin1", ""}), + }, + { + name: "should add the default preinstalled plugin and the one defined with version", + rawInput: "plugin1@1.0.0", + expected: append(defaultPreinstallPluginsList, InstallPlugin{"plugin1", "1.0.0"}), + }, + { + 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: append(defaultPreinstallPluginsList, InstallPlugin{"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.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.PreinstallPlugins, tc.expected) + if tc.disableAsync { + require.Equal(t, cfg.PreinstallPluginsAsync, false) + } + }) + } + }) }