From ae373c662c65562def7f07f27f2218319ed6347e Mon Sep 17 00:00:00 2001 From: Will Browne Date: Wed, 24 May 2023 14:02:14 +0200 Subject: [PATCH] Plugins: Refactor env vars to dedicated service (#68960) * add env vars service * fix tests * fix more tests --- go.mod | 2 +- .../backendplugin/grpcplugin/client.go | 12 +- pkg/plugins/envvars/envvars.go | 132 +++++++ pkg/plugins/envvars/envvars_test.go | 304 +++++++++++++++ .../manager/loader/initializer/initializer.go | 124 +----- .../loader/initializer/initializer_test.go | 355 +----------------- 6 files changed, 470 insertions(+), 459 deletions(-) create mode 100644 pkg/plugins/envvars/envvars.go create mode 100644 pkg/plugins/envvars/envvars_test.go diff --git a/go.mod b/go.mod index 80588568cb6..be09c0782ad 100644 --- a/go.mod +++ b/go.mod @@ -121,7 +121,7 @@ require ( gopkg.in/mail.v2 v2.3.1 gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 - xorm.io/builder v0.3.6 // indirect + xorm.io/builder v0.3.6 xorm.io/core v0.7.3 xorm.io/xorm v0.8.2 ) diff --git a/pkg/plugins/backendplugin/grpcplugin/client.go b/pkg/plugins/backendplugin/grpcplugin/client.go index 39a00ff1ba3..f363d4a5bfb 100644 --- a/pkg/plugins/backendplugin/grpcplugin/client.go +++ b/pkg/plugins/backendplugin/grpcplugin/client.go @@ -83,10 +83,20 @@ func getV2PluginSet() goplugin.PluginSet { // NewBackendPlugin creates a new backend plugin factory used for registering a backend plugin. func NewBackendPlugin(pluginID, executablePath string) backendplugin.PluginFactoryFunc { + return newBackendPlugin(pluginID, executablePath, true) +} + +// NewUnmanagedBackendPlugin creates a new backend plugin factory used for registering an unmanaged backend plugin. +func NewUnmanagedBackendPlugin(pluginID, executablePath string) backendplugin.PluginFactoryFunc { + return newBackendPlugin(pluginID, executablePath, false) +} + +// NewBackendPlugin creates a new backend plugin factory used for registering a backend plugin. +func newBackendPlugin(pluginID, executablePath string, managed bool) backendplugin.PluginFactoryFunc { return newPlugin(PluginDescriptor{ pluginID: pluginID, executablePath: executablePath, - managed: true, + managed: managed, versionedPlugins: map[int]goplugin.PluginSet{ grpcplugin.ProtocolVersion: getV2PluginSet(), }, diff --git a/pkg/plugins/envvars/envvars.go b/pkg/plugins/envvars/envvars.go new file mode 100644 index 00000000000..cc4b77b8a8d --- /dev/null +++ b/pkg/plugins/envvars/envvars.go @@ -0,0 +1,132 @@ +package envvars + +import ( + "context" + "fmt" + "os" + "strconv" + "strings" + + "github.com/grafana/grafana-aws-sdk/pkg/awsds" + "github.com/grafana/grafana-azure-sdk-go/azsettings" + "github.com/grafana/grafana-plugin-sdk-go/backend/proxy" + + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/plugins/config" +) + +type Provider interface { + Get(ctx context.Context, p *plugins.Plugin) []string +} + +type Service struct { + cfg *config.Cfg + license plugins.Licensing +} + +func NewProvider(cfg *config.Cfg, license plugins.Licensing) *Service { + return &Service{ + cfg: cfg, + license: license, + } +} + +func (s *Service) Get(_ context.Context, p *plugins.Plugin) []string { + hostEnv := []string{ + fmt.Sprintf("GF_VERSION=%s", s.cfg.BuildVersion), + } + + if s.license != nil { + hostEnv = append( + hostEnv, + fmt.Sprintf("GF_EDITION=%s", s.license.Edition()), + fmt.Sprintf("GF_ENTERPRISE_LICENSE_PATH=%s", s.license.Path()), + fmt.Sprintf("GF_ENTERPRISE_APP_URL=%s", s.license.AppURL()), + ) + hostEnv = append(hostEnv, s.license.Environment()...) + } + + hostEnv = append(hostEnv, s.awsEnvVars()...) + hostEnv = append(hostEnv, s.secureSocksProxyEnvVars()...) + hostEnv = append(hostEnv, azsettings.WriteToEnvStr(s.cfg.Azure)...) + hostEnv = append(hostEnv, s.tracingEnvVars(p)...) + + ev := getPluginSettings(p.ID, s.cfg).asEnvVar("GF_PLUGIN", hostEnv) + return ev +} + +func (s *Service) tracingEnvVars(plugin *plugins.Plugin) []string { + var pluginTracingEnabled bool + if v, exists := s.cfg.PluginSettings[plugin.ID]["tracing"]; exists { + pluginTracingEnabled = v == "true" + } + if !s.cfg.Tracing.IsEnabled() || !pluginTracingEnabled { + return nil + } + + var vars []string + if plugin.Info.Version != "" { + vars = append(vars, fmt.Sprintf("GF_PLUGIN_VERSION=%s", plugin.Info.Version)) + } + return append( + vars, + fmt.Sprintf("GF_INSTANCE_OTLP_ADDRESS=%s", s.cfg.Tracing.OpenTelemetry.Address), + fmt.Sprintf("GF_INSTANCE_OTLP_PROPAGATION=%s", s.cfg.Tracing.OpenTelemetry.Propagation), + ) +} + +func (s *Service) awsEnvVars() []string { + var variables []string + if s.cfg.AWSAssumeRoleEnabled { + variables = append(variables, awsds.AssumeRoleEnabledEnvVarKeyName+"=true") + } + if len(s.cfg.AWSAllowedAuthProviders) > 0 { + variables = append(variables, awsds.AllowedAuthProvidersEnvVarKeyName+"="+strings.Join(s.cfg.AWSAllowedAuthProviders, ",")) + } + + return variables +} + +func (s *Service) secureSocksProxyEnvVars() []string { + var variables []string + if s.cfg.ProxySettings.Enabled { + variables = append(variables, proxy.PluginSecureSocksProxyClientCert+"="+s.cfg.ProxySettings.ClientCert) + variables = append(variables, proxy.PluginSecureSocksProxyClientKey+"="+s.cfg.ProxySettings.ClientKey) + variables = append(variables, proxy.PluginSecureSocksProxyRootCACert+"="+s.cfg.ProxySettings.RootCA) + variables = append(variables, proxy.PluginSecureSocksProxyProxyAddress+"="+s.cfg.ProxySettings.ProxyAddress) + variables = append(variables, proxy.PluginSecureSocksProxyServerName+"="+s.cfg.ProxySettings.ServerName) + variables = append(variables, proxy.PluginSecureSocksProxyEnabled+"="+strconv.FormatBool(s.cfg.ProxySettings.Enabled)) + } + + return variables +} + +type pluginSettings map[string]string + +func getPluginSettings(pluginID string, cfg *config.Cfg) pluginSettings { + ps := pluginSettings{} + for k, v := range cfg.PluginSettings[pluginID] { + if k == "path" || strings.ToLower(k) == "id" { + continue + } + ps[k] = v + } + + return ps +} + +func (ps pluginSettings) asEnvVar(prefix string, hostEnv []string) []string { + env := make([]string, 0, len(ps)) + for k, v := range ps { + key := fmt.Sprintf("%s_%s", prefix, strings.ToUpper(k)) + if value := os.Getenv(key); value != "" { + v = value + } + + env = append(env, fmt.Sprintf("%s=%s", key, v)) + } + + env = append(env, hostEnv...) + + return env +} diff --git a/pkg/plugins/envvars/envvars_test.go b/pkg/plugins/envvars/envvars_test.go new file mode 100644 index 00000000000..550c0648729 --- /dev/null +++ b/pkg/plugins/envvars/envvars_test.go @@ -0,0 +1,304 @@ +package envvars + +import ( + "context" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/plugins/config" + "github.com/grafana/grafana/pkg/plugins/manager/fakes" + "github.com/grafana/grafana/pkg/setting" +) + +func TestInitializer_envVars(t *testing.T) { + t.Run("backend datasource with license", func(t *testing.T) { + p := &plugins.Plugin{ + JSONData: plugins.JSONData{ + ID: "test", + }, + } + + licensing := &fakes.FakeLicensingService{ + LicenseEdition: "test", + TokenRaw: "token", + LicensePath: "/path/to/ent/license", + LicenseAppURL: "https://myorg.com/", + } + + envVarsProvider := NewProvider(&config.Cfg{ + PluginSettings: map[string]map[string]string{ + "test": { + "custom_env_var": "customVal", + }, + }, + }, licensing) + + envVars := envVarsProvider.Get(context.Background(), p) + assert.Len(t, envVars, 6) + assert.Equal(t, "GF_PLUGIN_CUSTOM_ENV_VAR=customVal", envVars[0]) + assert.Equal(t, "GF_VERSION=", envVars[1]) + assert.Equal(t, "GF_EDITION=test", envVars[2]) + assert.Equal(t, "GF_ENTERPRISE_LICENSE_PATH=/path/to/ent/license", envVars[3]) + assert.Equal(t, "GF_ENTERPRISE_APP_URL=https://myorg.com/", envVars[4]) + assert.Equal(t, "GF_ENTERPRISE_LICENSE_TEXT=token", envVars[5]) + }) +} + +func TestInitializer_tracingEnvironmentVariables(t *testing.T) { + const pluginID = "plugin_id" + + defaultPlugin := &plugins.Plugin{ + JSONData: plugins.JSONData{ + ID: pluginID, + Info: plugins.Info{Version: "1.0.0"}, + }, + } + pluginWithoutVersion := &plugins.Plugin{ + JSONData: plugins.JSONData{ID: pluginID}, + } + + defaultOTelCfg := config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "", + } + + expDefaultOtlp := func(t *testing.T, envVars []string) { + found := map[string]bool{ + "address": false, + "plugin_version": false, + "propagation": false, + } + setFound := func(v string) { + require.False(t, found[v], "duplicate env var found") + found[v] = true + } + for _, v := range envVars { + switch v { + case "GF_PLUGIN_VERSION=1.0.0": + setFound("plugin_version") + case "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317": + setFound("address") + case "GF_INSTANCE_OTLP_PROPAGATION=": + setFound("propagation") + } + } + for k, f := range found { + require.Truef(t, f, "%q env var not found: %+v", k, envVars) + } + } + expNoTracing := func(t *testing.T, envVars []string) { + for _, v := range envVars { + assert.False(t, strings.HasPrefix(v, "GF_TRACING"), "should not have tracing env var") + assert.False( + t, + strings.HasPrefix(v, "GF_PLUGIN_VERSION"), + "GF_PLUGIN_VERSION is tracing-only and should not be present when tracing is disabled", + ) + } + } + expGfPluginVersionNotPresent := func(t *testing.T, envVars []string) { + for _, e := range envVars { + assert.False(t, strings.HasPrefix("GF_PLUGIN_VERSION=", e), "GF_PLUGIN_VERSION shouldn't be present") + } + } + expGfPluginVersionPresent := func(t *testing.T, envVars []string) { + var found bool + for _, e := range envVars { + if e != "GF_PLUGIN_VERSION=1.0.0" { + continue + } + assert.False(t, found, "GF_PLUGIN_VERSION is present multiple times") + found = true + } + assert.Truef(t, found, "GF_PLUGIN_VERSION is not present: %+v", envVars) + } + + for _, tc := range []struct { + name string + cfg *config.Cfg + plugin *plugins.Plugin + exp func(t *testing.T, envVars []string) + }{ + { + name: "otel not configured", + cfg: &config.Cfg{ + Tracing: config.Tracing{}, + }, + plugin: defaultPlugin, + exp: expNoTracing, + }, + { + name: "otel not configured but plugin-tracing enabled", + cfg: &config.Cfg{ + Tracing: config.Tracing{}, + PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, + }, + plugin: defaultPlugin, + exp: expNoTracing, + }, + { + name: "otlp no propagation plugin enabled", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, + PluginSettings: map[string]map[string]string{ + pluginID: {"tracing": "true"}, + }, + }, + plugin: defaultPlugin, + exp: expDefaultOtlp, + }, + { + name: "otlp no propagation disabled by default", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, + }, + plugin: defaultPlugin, + exp: expNoTracing, + }, + { + name: "otlp propagation plugin enabled", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "w3c", + }, + }, + PluginSettings: map[string]map[string]string{ + pluginID: {"tracing": "true"}, + }, + }, + plugin: defaultPlugin, + exp: func(t *testing.T, envVars []string) { + assert.Len(t, envVars, 5) + assert.Equal(t, "GF_PLUGIN_TRACING=true", envVars[0]) + assert.Equal(t, "GF_VERSION=", envVars[1]) + assert.Equal(t, "GF_PLUGIN_VERSION=1.0.0", envVars[2]) + assert.Equal(t, "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317", envVars[3]) + assert.Equal(t, "GF_INSTANCE_OTLP_PROPAGATION=w3c", envVars[4]) + }, + }, + { + name: "otlp enabled composite propagation", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "w3c,jaeger", + }, + }, + PluginSettings: map[string]map[string]string{ + pluginID: {"tracing": "true"}, + }, + }, + plugin: defaultPlugin, + exp: func(t *testing.T, envVars []string) { + assert.Len(t, envVars, 5) + assert.Equal(t, "GF_PLUGIN_TRACING=true", envVars[0]) + assert.Equal(t, "GF_VERSION=", envVars[1]) + assert.Equal(t, "GF_PLUGIN_VERSION=1.0.0", envVars[2]) + assert.Equal(t, "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317", envVars[3]) + assert.Equal(t, "GF_INSTANCE_OTLP_PROPAGATION=w3c,jaeger", envVars[4]) + }, + }, + { + name: "otlp no propagation disabled by default", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "w3c", + }, + }, + }, + plugin: defaultPlugin, + exp: expNoTracing, + }, + { + name: "disabled on plugin", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, + PluginSettings: setting.PluginSettings{ + pluginID: map[string]string{"tracing": "false"}, + }, + }, + plugin: defaultPlugin, + exp: expNoTracing, + }, + { + name: "disabled on plugin with other plugin settings", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, + PluginSettings: map[string]map[string]string{ + pluginID: {"some_other_option": "true"}, + }, + }, + plugin: defaultPlugin, + exp: expNoTracing, + }, + { + name: "enabled on plugin with other plugin settings", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, + PluginSettings: map[string]map[string]string{ + pluginID: {"some_other_option": "true", "tracing": "true"}, + }, + }, + plugin: defaultPlugin, + exp: expDefaultOtlp, + }, + { + name: "GF_PLUGIN_VERSION is not present if tracing is disabled", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{}, + }, + PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, + }, + plugin: defaultPlugin, + exp: expGfPluginVersionNotPresent, + }, + { + name: "GF_PLUGIN_VERSION is present if tracing is enabled and plugin has version", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, + PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, + }, + plugin: defaultPlugin, + exp: expGfPluginVersionPresent, + }, + { + name: "GF_PLUGIN_VERSION is not present if tracing is enabled but plugin doesn't have a version", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{}, + }, + PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, + }, + plugin: pluginWithoutVersion, + exp: expGfPluginVersionNotPresent, + }, + } { + t.Run(tc.name, func(t *testing.T) { + envVarsProvider := NewProvider(tc.cfg, nil) + envVars := envVarsProvider.Get(context.Background(), tc.plugin) + tc.exp(t, envVars) + }) + } +} diff --git a/pkg/plugins/manager/loader/initializer/initializer.go b/pkg/plugins/manager/loader/initializer/initializer.go index 09aa6bbf64a..2c932a4d079 100644 --- a/pkg/plugins/manager/loader/initializer/initializer.go +++ b/pkg/plugins/manager/loader/initializer/initializer.go @@ -2,33 +2,22 @@ package initializer import ( "context" - "fmt" - "os" - "strconv" - "strings" - - "github.com/grafana/grafana-aws-sdk/pkg/awsds" - "github.com/grafana/grafana-azure-sdk-go/azsettings" - "github.com/grafana/grafana-plugin-sdk-go/backend/proxy" + "errors" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/config" - "github.com/grafana/grafana/pkg/plugins/log" + "github.com/grafana/grafana/pkg/plugins/envvars" ) type Initializer struct { - cfg *config.Cfg - license plugins.Licensing + envVarProvider envvars.Provider backendProvider plugins.BackendFactoryProvider - log log.Logger } func New(cfg *config.Cfg, backendProvider plugins.BackendFactoryProvider, license plugins.Licensing) Initializer { return Initializer{ - cfg: cfg, - license: license, + envVarProvider: envvars.NewProvider(cfg, license), backendProvider: backendProvider, - log: log.New("plugin.initializer"), } } @@ -36,10 +25,11 @@ func (i *Initializer) Initialize(ctx context.Context, p *plugins.Plugin) error { if p.Backend { backendFactory := i.backendProvider.BackendFactory(ctx, p) if backendFactory == nil { - return fmt.Errorf("could not find backend factory for plugin") + return errors.New("could not find backend factory for plugin") } - if backendClient, err := backendFactory(p.ID, p.Logger(), i.envVars(p)); err != nil { + env := i.envVarProvider.Get(ctx, p) + if backendClient, err := backendFactory(p.ID, p.Logger(), env); err != nil { return err } else { p.RegisterClient(backendClient) @@ -48,103 +38,3 @@ func (i *Initializer) Initialize(ctx context.Context, p *plugins.Plugin) error { return nil } - -func (i *Initializer) envVars(plugin *plugins.Plugin) []string { - hostEnv := []string{ - fmt.Sprintf("GF_VERSION=%s", i.cfg.BuildVersion), - } - - if i.license != nil { - hostEnv = append( - hostEnv, - fmt.Sprintf("GF_EDITION=%s", i.license.Edition()), - fmt.Sprintf("GF_ENTERPRISE_LICENSE_PATH=%s", i.license.Path()), - fmt.Sprintf("GF_ENTERPRISE_APP_URL=%s", i.license.AppURL()), - ) - hostEnv = append(hostEnv, i.license.Environment()...) - } - - hostEnv = append(hostEnv, i.awsEnvVars()...) - hostEnv = append(hostEnv, i.secureSocksProxyEnvVars()...) - hostEnv = append(hostEnv, azsettings.WriteToEnvStr(i.cfg.Azure)...) - hostEnv = append(hostEnv, i.tracingEnvVars(plugin)...) - - ev := getPluginSettings(plugin.ID, i.cfg).asEnvVar("GF_PLUGIN", hostEnv) - return ev -} - -func (i *Initializer) tracingEnvVars(plugin *plugins.Plugin) []string { - var pluginTracingEnabled bool - if v, exists := i.cfg.PluginSettings[plugin.ID]["tracing"]; exists { - pluginTracingEnabled = v == "true" - } - if !i.cfg.Tracing.IsEnabled() || !pluginTracingEnabled { - return nil - } - - var vars []string - if plugin.Info.Version != "" { - vars = append(vars, fmt.Sprintf("GF_PLUGIN_VERSION=%s", plugin.Info.Version)) - } - return append( - vars, - fmt.Sprintf("GF_INSTANCE_OTLP_ADDRESS=%s", i.cfg.Tracing.OpenTelemetry.Address), - fmt.Sprintf("GF_INSTANCE_OTLP_PROPAGATION=%s", i.cfg.Tracing.OpenTelemetry.Propagation), - ) -} - -func (i *Initializer) awsEnvVars() []string { - var variables []string - if i.cfg.AWSAssumeRoleEnabled { - variables = append(variables, awsds.AssumeRoleEnabledEnvVarKeyName+"=true") - } - if len(i.cfg.AWSAllowedAuthProviders) > 0 { - variables = append(variables, awsds.AllowedAuthProvidersEnvVarKeyName+"="+strings.Join(i.cfg.AWSAllowedAuthProviders, ",")) - } - - return variables -} - -func (i *Initializer) secureSocksProxyEnvVars() []string { - var variables []string - if i.cfg.ProxySettings.Enabled { - variables = append(variables, proxy.PluginSecureSocksProxyClientCert+"="+i.cfg.ProxySettings.ClientCert) - variables = append(variables, proxy.PluginSecureSocksProxyClientKey+"="+i.cfg.ProxySettings.ClientKey) - variables = append(variables, proxy.PluginSecureSocksProxyRootCACert+"="+i.cfg.ProxySettings.RootCA) - variables = append(variables, proxy.PluginSecureSocksProxyProxyAddress+"="+i.cfg.ProxySettings.ProxyAddress) - variables = append(variables, proxy.PluginSecureSocksProxyServerName+"="+i.cfg.ProxySettings.ServerName) - variables = append(variables, proxy.PluginSecureSocksProxyEnabled+"="+strconv.FormatBool(i.cfg.ProxySettings.Enabled)) - } - - return variables -} - -type pluginSettings map[string]string - -func (ps pluginSettings) asEnvVar(prefix string, hostEnv []string) []string { - env := make([]string, 0, len(ps)) - for k, v := range ps { - key := fmt.Sprintf("%s_%s", prefix, strings.ToUpper(k)) - if value := os.Getenv(key); value != "" { - v = value - } - - env = append(env, fmt.Sprintf("%s=%s", key, v)) - } - - env = append(env, hostEnv...) - - return env -} - -func getPluginSettings(pluginID string, cfg *config.Cfg) pluginSettings { - ps := pluginSettings{} - for k, v := range cfg.PluginSettings[pluginID] { - if k == "path" || strings.ToLower(k) == "id" { - continue - } - ps[k] = v - } - - return ps -} diff --git a/pkg/plugins/manager/loader/initializer/initializer_test.go b/pkg/plugins/manager/loader/initializer/initializer_test.go index 010998da890..f269f33161d 100644 --- a/pkg/plugins/manager/loader/initializer/initializer_test.go +++ b/pkg/plugins/manager/loader/initializer/initializer_test.go @@ -2,18 +2,13 @@ package initializer import ( "context" - "strings" "testing" - "github.com/grafana/grafana/pkg/setting" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin" - "github.com/grafana/grafana/pkg/plugins/config" "github.com/grafana/grafana/pkg/plugins/log" - "github.com/grafana/grafana/pkg/plugins/manager/fakes" ) func TestInitializer_Initialize(t *testing.T) { @@ -34,11 +29,10 @@ func TestInitializer_Initialize(t *testing.T) { } i := &Initializer{ - cfg: &config.Cfg{}, - log: log.NewTestLogger(), backendProvider: &fakeBackendProvider{ plugin: p, }, + envVarProvider: &fakeEnvVarsProvider{}, } err := i.Initialize(context.Background(), p) @@ -63,11 +57,10 @@ func TestInitializer_Initialize(t *testing.T) { } i := &Initializer{ - cfg: &config.Cfg{}, - log: log.NewTestLogger(), backendProvider: &fakeBackendProvider{ plugin: p, }, + envVarProvider: &fakeEnvVarsProvider{}, } err := i.Initialize(context.Background(), p) @@ -92,11 +85,10 @@ func TestInitializer_Initialize(t *testing.T) { } i := &Initializer{ - cfg: &config.Cfg{}, - log: log.NewTestLogger(), backendProvider: &fakeBackendProvider{ plugin: p, }, + envVarProvider: &fakeEnvVarsProvider{}, } err := i.Initialize(context.Background(), p) @@ -115,11 +107,10 @@ func TestInitializer_Initialize(t *testing.T) { } i := &Initializer{ - cfg: &config.Cfg{}, - log: log.NewTestLogger(), backendProvider: &fakeBackendProvider{ plugin: p, }, + envVarProvider: &fakeEnvVarsProvider{}, } err := i.Initialize(context.Background(), p) @@ -131,333 +122,6 @@ func TestInitializer_Initialize(t *testing.T) { }) } -func TestInitializer_envVars(t *testing.T) { - t.Run("backend datasource with license", func(t *testing.T) { - p := &plugins.Plugin{ - JSONData: plugins.JSONData{ - ID: "test", - }, - } - - licensing := &fakes.FakeLicensingService{ - LicenseEdition: "test", - TokenRaw: "token", - LicensePath: "/path/to/ent/license", - LicenseAppURL: "https://myorg.com/", - } - - i := &Initializer{ - cfg: &config.Cfg{ - PluginSettings: map[string]map[string]string{ - "test": { - "custom_env_var": "customVal", - }, - }, - }, - license: licensing, - log: log.NewTestLogger(), - backendProvider: &fakeBackendProvider{ - plugin: p, - }, - } - - envVars := i.envVars(p) - assert.Len(t, envVars, 6) - assert.Equal(t, "GF_PLUGIN_CUSTOM_ENV_VAR=customVal", envVars[0]) - assert.Equal(t, "GF_VERSION=", envVars[1]) - assert.Equal(t, "GF_EDITION=test", envVars[2]) - assert.Equal(t, "GF_ENTERPRISE_LICENSE_PATH=/path/to/ent/license", envVars[3]) - assert.Equal(t, "GF_ENTERPRISE_APP_URL=https://myorg.com/", envVars[4]) - assert.Equal(t, "GF_ENTERPRISE_LICENSE_TEXT=token", envVars[5]) - }) -} - -func TestInitializer_tracingEnvironmentVariables(t *testing.T) { - const pluginID = "plugin_id" - - defaultPlugin := &plugins.Plugin{ - JSONData: plugins.JSONData{ - ID: pluginID, - Info: plugins.Info{Version: "1.0.0"}, - }, - } - pluginWithoutVersion := &plugins.Plugin{ - JSONData: plugins.JSONData{ID: pluginID}, - } - - defaultOTelCfg := config.OpenTelemetryCfg{ - Address: "127.0.0.1:4317", - Propagation: "", - } - - expDefaultOtlp := func(t *testing.T, envVars []string) { - found := map[string]bool{ - "address": false, - "plugin_version": false, - "propagation": false, - } - setFound := func(v string) { - require.False(t, found[v], "duplicate env var found") - found[v] = true - } - for _, v := range envVars { - switch v { - case "GF_PLUGIN_VERSION=1.0.0": - setFound("plugin_version") - case "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317": - setFound("address") - case "GF_INSTANCE_OTLP_PROPAGATION=": - setFound("propagation") - } - } - for k, f := range found { - require.Truef(t, f, "%q env var not found: %+v", k, envVars) - } - } - expNoTracing := func(t *testing.T, envVars []string) { - for _, v := range envVars { - assert.False(t, strings.HasPrefix(v, "GF_TRACING"), "should not have tracing env var") - assert.False( - t, - strings.HasPrefix(v, "GF_PLUGIN_VERSION"), - "GF_PLUGIN_VERSION is tracing-only and should not be present when tracing is disabled", - ) - } - } - expGfPluginVersionNotPresent := func(t *testing.T, envVars []string) { - for _, e := range envVars { - assert.False(t, strings.HasPrefix("GF_PLUGIN_VERSION=", e), "GF_PLUGIN_VERSION shouldn't be present") - } - } - expGfPluginVersionPresent := func(t *testing.T, envVars []string) { - var found bool - for _, e := range envVars { - if e != "GF_PLUGIN_VERSION=1.0.0" { - continue - } - assert.False(t, found, "GF_PLUGIN_VERSION is present multiple times") - found = true - } - assert.Truef(t, found, "GF_PLUGIN_VERSION is not present: %+v", envVars) - } - - for _, tc := range []struct { - name string - cfg *config.Cfg - plugin *plugins.Plugin - exp func(t *testing.T, envVars []string) - }{ - { - name: "otel not configured", - cfg: &config.Cfg{ - Tracing: config.Tracing{}, - }, - plugin: defaultPlugin, - exp: expNoTracing, - }, - { - name: "otel not configured but plugin-tracing enabled", - cfg: &config.Cfg{ - Tracing: config.Tracing{}, - PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, - }, - plugin: defaultPlugin, - exp: expNoTracing, - }, - { - name: "otlp no propagation plugin enabled", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: defaultOTelCfg, - }, - PluginSettings: map[string]map[string]string{ - pluginID: {"tracing": "true"}, - }, - }, - plugin: defaultPlugin, - exp: expDefaultOtlp, - }, - { - name: "otlp no propagation disabled by default", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: defaultOTelCfg, - }, - }, - plugin: defaultPlugin, - exp: expNoTracing, - }, - { - name: "otlp propagation plugin enabled", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: config.OpenTelemetryCfg{ - Address: "127.0.0.1:4317", - Propagation: "w3c", - }, - }, - PluginSettings: map[string]map[string]string{ - pluginID: {"tracing": "true"}, - }, - }, - plugin: defaultPlugin, - exp: func(t *testing.T, envVars []string) { - assert.Len(t, envVars, 5) - assert.Equal(t, "GF_PLUGIN_TRACING=true", envVars[0]) - assert.Equal(t, "GF_VERSION=", envVars[1]) - assert.Equal(t, "GF_PLUGIN_VERSION=1.0.0", envVars[2]) - assert.Equal(t, "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317", envVars[3]) - assert.Equal(t, "GF_INSTANCE_OTLP_PROPAGATION=w3c", envVars[4]) - }, - }, - { - name: "otlp enabled composite propagation", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: config.OpenTelemetryCfg{ - Address: "127.0.0.1:4317", - Propagation: "w3c,jaeger", - }, - }, - PluginSettings: map[string]map[string]string{ - pluginID: {"tracing": "true"}, - }, - }, - plugin: defaultPlugin, - exp: func(t *testing.T, envVars []string) { - assert.Len(t, envVars, 5) - assert.Equal(t, "GF_PLUGIN_TRACING=true", envVars[0]) - assert.Equal(t, "GF_VERSION=", envVars[1]) - assert.Equal(t, "GF_PLUGIN_VERSION=1.0.0", envVars[2]) - assert.Equal(t, "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317", envVars[3]) - assert.Equal(t, "GF_INSTANCE_OTLP_PROPAGATION=w3c,jaeger", envVars[4]) - }, - }, - { - name: "otlp no propagation disabled by default", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: config.OpenTelemetryCfg{ - Address: "127.0.0.1:4317", - Propagation: "w3c", - }, - }, - }, - plugin: defaultPlugin, - exp: expNoTracing, - }, - { - name: "disabled on plugin", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: defaultOTelCfg, - }, - PluginSettings: setting.PluginSettings{ - pluginID: map[string]string{"tracing": "false"}, - }, - }, - plugin: defaultPlugin, - exp: expNoTracing, - }, - { - name: "disabled on plugin with other plugin settings", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: defaultOTelCfg, - }, - PluginSettings: map[string]map[string]string{ - pluginID: {"some_other_option": "true"}, - }, - }, - plugin: defaultPlugin, - exp: expNoTracing, - }, - { - name: "enabled on plugin with other plugin settings", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: defaultOTelCfg, - }, - PluginSettings: map[string]map[string]string{ - pluginID: {"some_other_option": "true", "tracing": "true"}, - }, - }, - plugin: defaultPlugin, - exp: expDefaultOtlp, - }, - { - name: "GF_PLUGIN_VERSION is not present if tracing is disabled", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: config.OpenTelemetryCfg{}, - }, - PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, - }, - plugin: defaultPlugin, - exp: expGfPluginVersionNotPresent, - }, - { - name: "GF_PLUGIN_VERSION is present if tracing is enabled and plugin has version", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: defaultOTelCfg, - }, - PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, - }, - plugin: defaultPlugin, - exp: expGfPluginVersionPresent, - }, - { - name: "GF_PLUGIN_VERSION is not present if tracing is enabled but plugin doesn't have a version", - cfg: &config.Cfg{ - Tracing: config.Tracing{ - OpenTelemetry: config.OpenTelemetryCfg{}, - }, - PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, - }, - plugin: pluginWithoutVersion, - exp: expGfPluginVersionNotPresent, - }, - } { - t.Run(tc.name, func(t *testing.T) { - i := &Initializer{ - cfg: tc.cfg, - log: log.NewTestLogger(), - } - envVars := i.envVars(tc.plugin) - tc.exp(t, envVars) - }) - } -} - -func TestInitializer_getAWSEnvironmentVariables(t *testing.T) { - -} - -func TestInitializer_handleModuleDefaults(t *testing.T) { - -} - -func Test_defaultLogoPath(t *testing.T) { - -} - -func Test_evalRelativePluginUrlPath(t *testing.T) { - -} - -func Test_getPluginLogoUrl(t *testing.T) { - -} - -func Test_getPluginSettings(t *testing.T) { - -} - -func Test_pluginSettings_ToEnv(t *testing.T) { - -} - type fakeBackendProvider struct { plugins.BackendFactoryProvider @@ -469,3 +133,14 @@ func (f *fakeBackendProvider) BackendFactory(_ context.Context, _ *plugins.Plugi return f.plugin, nil } } + +type fakeEnvVarsProvider struct { + GetFunc func(ctx context.Context, p *plugins.Plugin) []string +} + +func (f *fakeEnvVarsProvider) Get(ctx context.Context, p *plugins.Plugin) []string { + if f.GetFunc != nil { + return f.GetFunc(ctx, p) + } + return nil +}