mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			184 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| package setting
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| 
 | |
| 	"gopkg.in/ini.v1"
 | |
| 
 | |
| 	"github.com/grafana/grafana/pkg/util"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	PluginUpdateStrategyLatest = "latest"
 | |
| 	PluginUpdateStrategyMinor  = "minor"
 | |
| )
 | |
| 
 | |
| // 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
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	defaultPreinstallPlugins = map[string]InstallPlugin{
 | |
| 		// Default preinstalled plugins
 | |
| 		"grafana-lokiexplore-app":      {ID: "grafana-lokiexplore-app"},
 | |
| 		"grafana-pyroscope-app":        {ID: "grafana-pyroscope-app"},
 | |
| 		"grafana-exploretraces-app":    {ID: "grafana-exploretraces-app"},
 | |
| 		"grafana-metricsdrilldown-app": {ID: "grafana-metricsdrilldown-app"},
 | |
| 	}
 | |
| )
 | |
| 
 | |
| func (cfg *Cfg) migrateInstallPluginsToPreinstallPluginsSync(rawInstallPlugins, installPluginsForce string, preinstallPluginsSync map[string]InstallPlugin) {
 | |
| 	if strings.ToLower(installPluginsForce) == "true" || rawInstallPlugins == "" {
 | |
| 		cfg.Logger.Debug("GF_INSTALL_PLUGINS_FORCE is set to true, skipping migration of GF_INSTALL_PLUGINS to GF_PLUGINS_PREINSTALL_SYNC")
 | |
| 		return
 | |
| 	}
 | |
| 	installPluginsEntries := strings.Split(rawInstallPlugins, ",")
 | |
| 
 | |
| 	// Format 1: ID only (e.g., "grafana-clock-panel")
 | |
| 	// Format 2: ID with version (e.g., "grafana-clock-panel 1.0.1")
 | |
| 	// Format 3: URL with folder (e.g., "https://grafana.com/api/plugins/grafana-clock-panel/versions/latest/download;grafana-clock-panel")
 | |
| 	pluginRegex := regexp.MustCompile(`(?:([^;]+);)?([^;\s]+)(?:\s+(.+))?`)
 | |
| 	for _, entry := range installPluginsEntries {
 | |
| 		trimmedEntry := strings.TrimSpace(entry)
 | |
| 		if trimmedEntry == "" {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		matches := pluginRegex.FindStringSubmatch(trimmedEntry)
 | |
| 
 | |
| 		if matches == nil {
 | |
| 			cfg.Logger.Debug("No match found for entry: ", trimmedEntry)
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		url := ""
 | |
| 		if len(matches) > 1 {
 | |
| 			url = strings.TrimSpace(matches[1])
 | |
| 		}
 | |
| 
 | |
| 		id := ""
 | |
| 		if len(matches) > 2 {
 | |
| 			id = strings.TrimSpace(matches[2])
 | |
| 		}
 | |
| 		if _, exists := preinstallPluginsSync[id]; exists {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		version := ""
 | |
| 		if len(matches) > 3 {
 | |
| 			version = strings.TrimSpace(matches[3])
 | |
| 		}
 | |
| 		if id != "" {
 | |
| 			preinstallPluginsSync[id] = InstallPlugin{ID: id, Version: version, URL: url}
 | |
| 		} else {
 | |
| 			cfg.Logger.Debug("No ID found for entry: ", trimmedEntry, "matches: ", matches)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (cfg *Cfg) processPreinstallPlugins(rawInstallPlugins []string, preinstallPlugins map[string]InstallPlugin) {
 | |
| 	// Add the plugins defined in the configuration
 | |
| 	for _, plugin := range rawInstallPlugins {
 | |
| 		parts := strings.Split(plugin, "@")
 | |
| 		id := parts[0]
 | |
| 		version := ""
 | |
| 		url := ""
 | |
| 		if len(parts) > 1 {
 | |
| 			version = parts[1]
 | |
| 			if len(parts) > 2 {
 | |
| 				url = parts[2]
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		preinstallPlugins[id] = InstallPlugin{id, version, url}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (cfg *Cfg) readPluginSettings(iniFile *ini.File) error {
 | |
| 	pluginsSection := iniFile.Section("plugins")
 | |
| 
 | |
| 	cfg.PluginsEnableAlpha = pluginsSection.Key("enable_alpha").MustBool(false)
 | |
| 	cfg.PluginsAppsSkipVerifyTLS = pluginsSection.Key("app_tls_skip_verify_insecure").MustBool(false)
 | |
| 	cfg.PluginSettings = extractPluginSettings(iniFile.Sections())
 | |
| 	cfg.PluginSkipPublicKeyDownload = pluginsSection.Key("public_key_retrieval_disabled").MustBool(false)
 | |
| 	cfg.PluginForcePublicKeyDownload = pluginsSection.Key("public_key_retrieval_on_startup").MustBool(false)
 | |
| 
 | |
| 	cfg.PluginsAllowUnsigned = util.SplitString(pluginsSection.Key("allow_loading_unsigned_plugins").MustString(""))
 | |
| 	cfg.DisablePlugins = util.SplitString(pluginsSection.Key("disable_plugins").MustString(""))
 | |
| 	cfg.HideAngularDeprecation = util.SplitString(pluginsSection.Key("hide_angular_deprecation").MustString(""))
 | |
| 	cfg.ForwardHostEnvVars = util.SplitString(pluginsSection.Key("forward_host_env_vars").MustString(""))
 | |
| 	disablePreinstall := pluginsSection.Key("preinstall_disabled").MustBool(false)
 | |
| 	if !disablePreinstall {
 | |
| 		rawInstallPluginsAsync := util.SplitString(pluginsSection.Key("preinstall").MustString(""))
 | |
| 		preinstallPluginsAsync := make(map[string]InstallPlugin)
 | |
| 		// Add the default preinstalled plugins to pre install plugins async list
 | |
| 		for _, plugin := range defaultPreinstallPlugins {
 | |
| 			preinstallPluginsAsync[plugin.ID] = plugin
 | |
| 		}
 | |
| 		if cfg.IsFeatureToggleEnabled("grafanaAdvisor") { // Use literal string to avoid circular dependency
 | |
| 			preinstallPluginsAsync["grafana-advisor-app"] = InstallPlugin{"grafana-advisor-app", "", ""}
 | |
| 		}
 | |
| 		cfg.processPreinstallPlugins(rawInstallPluginsAsync, preinstallPluginsAsync)
 | |
| 
 | |
| 		rawInstallPluginsSync := util.SplitString(pluginsSection.Key("preinstall_sync").MustString(""))
 | |
| 		preinstallPluginsSync := make(map[string]InstallPlugin)
 | |
| 		cfg.processPreinstallPlugins(rawInstallPluginsSync, preinstallPluginsSync)
 | |
| 		cfg.migrateInstallPluginsToPreinstallPluginsSync(os.Getenv("GF_INSTALL_PLUGINS"), os.Getenv("GF_INSTALL_PLUGINS_FORCE"), preinstallPluginsSync)
 | |
| 		// Remove from the list the plugins that have been disabled
 | |
| 		for _, disabledPlugin := range cfg.DisablePlugins {
 | |
| 			delete(preinstallPluginsAsync, disabledPlugin)
 | |
| 			delete(preinstallPluginsSync, disabledPlugin)
 | |
| 		}
 | |
| 		for _, plugin := range preinstallPluginsSync {
 | |
| 			cfg.PreinstallPluginsSync = append(cfg.PreinstallPluginsSync, plugin)
 | |
| 			// preinstallSync plugin has priority over preinstallAsync
 | |
| 			delete(preinstallPluginsAsync, plugin.ID)
 | |
| 		}
 | |
| 		for _, plugin := range preinstallPluginsAsync {
 | |
| 			cfg.PreinstallPluginsAsync = append(cfg.PreinstallPluginsAsync, plugin)
 | |
| 		}
 | |
| 
 | |
| 		installPluginsInAsync := pluginsSection.Key("preinstall_async").MustBool(true)
 | |
| 		if !installPluginsInAsync {
 | |
| 			for key, plugin := range preinstallPluginsAsync {
 | |
| 				if _, exists := preinstallPluginsSync[key]; !exists {
 | |
| 					cfg.PreinstallPluginsSync = append(cfg.PreinstallPluginsSync, plugin)
 | |
| 				}
 | |
| 			}
 | |
| 			cfg.PreinstallPluginsAsync = nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	cfg.PluginCatalogURL = pluginsSection.Key("plugin_catalog_url").MustString("https://grafana.com/grafana/plugins/")
 | |
| 	cfg.PluginAdminEnabled = pluginsSection.Key("plugin_admin_enabled").MustBool(true)
 | |
| 	cfg.PluginAdminExternalManageEnabled = pluginsSection.Key("plugin_admin_external_manage_enabled").MustBool(false)
 | |
| 	cfg.PluginCatalogHiddenPlugins = util.SplitString(pluginsSection.Key("plugin_catalog_hidden_plugins").MustString(""))
 | |
| 
 | |
| 	// Pull disabled plugins from the catalog
 | |
| 	cfg.PluginCatalogHiddenPlugins = append(cfg.PluginCatalogHiddenPlugins, cfg.DisablePlugins...)
 | |
| 
 | |
| 	// Plugins CDN settings
 | |
| 	cfg.PluginsCDNURLTemplate = strings.TrimRight(pluginsSection.Key("cdn_base_url").MustString(""), "/")
 | |
| 	cfg.PluginLogBackendRequests = pluginsSection.Key("log_backend_requests").MustBool(false)
 | |
| 
 | |
| 	cfg.PluginUpdateStrategy = pluginsSection.Key("update_strategy").In(PluginUpdateStrategyLatest, []string{PluginUpdateStrategyLatest, PluginUpdateStrategyMinor})
 | |
| 
 | |
| 	return nil
 | |
| }
 |