diff --git a/pkg/cmd/grafana-cli/commands/install_command_test.go b/pkg/cmd/grafana-cli/commands/install_command_test.go index 0f655296932..6d9c35c1f8f 100644 --- a/pkg/cmd/grafana-cli/commands/install_command_test.go +++ b/pkg/cmd/grafana-cli/commands/install_command_test.go @@ -4,7 +4,9 @@ import ( "fmt" "testing" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/commands/commandstest" "github.com/grafana/grafana/pkg/cmd/grafana-cli/utils" + "github.com/grafana/grafana/pkg/tests/testinfra" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) @@ -78,3 +80,60 @@ func TestValidateInput(t *testing.T) { }) } } + +func TestValidatePluginRepoConfig(t *testing.T) { + t.Run("Should use provided repo parameter for installation", func(t *testing.T) { + c, err := commandstest.NewCliContext(map[string]string{ + "repo": "https://example.com", + }) + + require.NoError(t, err) + require.Equal(t, "https://example.com", c.PluginRepoURL()) + }) + + t.Run("Should use provided repo parameter even if config is set", func(t *testing.T) { + c, err := commandstest.NewCliContext(map[string]string{ + "repo": "https://example.com", + "config": "/tmp/config.ini", + }) + + require.NoError(t, err) + require.Equal(t, "https://example.com", c.PluginRepoURL()) + }) + + t.Run("Should use config parameter if it is set", func(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + grafDir, cfgPath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ + GrafanaComAPIURL: "https://grafana-dev.com", + }) + + c, err := commandstest.NewCliContext(map[string]string{ + "config": cfgPath, + "homepath": grafDir, + }) + require.NoError(t, err) + repoURL := c.PluginRepoURL() + require.Equal(t, "https://grafana-dev.com/plugins", repoURL) + }) + + t.Run("Should use config overrides parameter if it is set alongside config parameter", func(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + // GrafanaComApiUrl is set to the default path https://grafana.com/api + grafDir, cfgPath := testinfra.CreateGrafDir(t) + + // overriding the GrafanaComApiUrl to https://grafana-dev.com + c, err := commandstest.NewCliContext(map[string]string{ + "config": cfgPath, + "homepath": grafDir, + "configOverrides": "cfg:grafana_com.api_url=https://grafana-dev.com", + }) + require.NoError(t, err) + repoURL := c.PluginRepoURL() + require.Equal(t, "https://grafana-dev.com/plugins", repoURL) + }) +} diff --git a/pkg/cmd/grafana-cli/utils/command_line.go b/pkg/cmd/grafana-cli/utils/command_line.go index aa83e46af2c..e394ab03769 100644 --- a/pkg/cmd/grafana-cli/utils/command_line.go +++ b/pkg/cmd/grafana-cli/utils/command_line.go @@ -1,9 +1,14 @@ package utils import ( + "slices" + "strings" + "github.com/urfave/cli/v2" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" "github.com/grafana/grafana/pkg/cmd/grafana-cli/models" + "github.com/grafana/grafana/pkg/setting" ) type CommandLine interface { @@ -52,7 +57,38 @@ func (c *ContextCommandLine) PluginDirectory() string { return c.String("pluginsDir") } +/* +The plugin repository URL is determined in the following order: +1. --repo flag value if it is specified +2. --repo flag value if set via the environment variable called "GF_PLUGIN_REPO" +3. --configOverrides parameter (only if --config is set too) +4. --config parameter, from which we are looking at GrafanaComAPIURL setting +5. fallback to default value which is https://grafana.com/api/plugins +**/ + func (c *ContextCommandLine) PluginRepoURL() string { + // if --repo flag is set, use it + // since the repo flag always has a value set by default we are checking in the flag lists if the --repo flag was provided at all. + if slices.Contains(c.FlagNames(), "repo") { + return c.String("repo") + } + + // if --config flag is set, try to get the GrafanaComAPIURL setting + if c.ConfigFile() != "" { + configOptions := strings.Split(c.String("configOverrides"), " ") + cfg, err := setting.NewCfgFromArgs(setting.CommandLineArgs{ + Config: c.ConfigFile(), + HomePath: c.HomePath(), + Args: append(configOptions, c.Args().Slice()...), + }) + + if err != nil { + logger.Debug("Could not parse config file", err) + } else if cfg.GrafanaComAPIURL != "" { + return cfg.GrafanaComAPIURL + "/plugins" + } + } + // fallback to default value return c.String("repo") } diff --git a/pkg/tests/testinfra/testinfra.go b/pkg/tests/testinfra/testinfra.go index bdeabb8ee9b..24b046d7aed 100644 --- a/pkg/tests/testinfra/testinfra.go +++ b/pkg/tests/testinfra/testinfra.go @@ -376,6 +376,13 @@ func CreateGrafDir(t *testing.T, opts ...GrafanaOpts) (string, string) { _, err = unifiedAlertingSection.NewKey("min_interval", o.NGAlertSchedulerBaseInterval.String()) require.NoError(t, err) } + + if o.GrafanaComAPIURL != "" { + grafanaComSection, err := getOrCreateSection("grafana_com") + require.NoError(t, err) + _, err = grafanaComSection.NewKey("api_url", o.GrafanaComAPIURL) + require.NoError(t, err) + } } logSection, err := getOrCreateSection("database") require.NoError(t, err) @@ -422,6 +429,7 @@ type GrafanaOpts struct { GRPCServerAddress string QueryRetries int64 APIServerStorageType string + GrafanaComAPIURL string } func CreateUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) *user.User {