Plugins: Local provider for meta (#114474)

This commit is contained in:
Will Browne
2025-12-17 16:25:54 +01:00
committed by GitHub
parent eb392b6149
commit e0711d9d1d
25 changed files with 1158 additions and 718 deletions
+20 -11
View File
@@ -2,16 +2,19 @@ package plugins
import (
"fmt"
"os"
authlib "github.com/grafana/authlib/types"
appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver"
pluginsapp "github.com/grafana/grafana/apps/plugins/pkg/app"
"github.com/grafana/grafana/apps/plugins/pkg/app/meta"
"github.com/grafana/grafana/pkg/configprovider"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/appinstaller"
grafanaauthorizer "github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginassets"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
)
var (
@@ -20,23 +23,26 @@ var (
)
type AppInstaller struct {
metaManager *meta.ProviderManager
cfgProvider configprovider.ConfigProvider
restConfigProvider apiserver.RestConfigProvider
*pluginsapp.PluginAppInstaller
}
func ProvideAppInstaller(accessControlService accesscontrol.Service, accessClient authlib.AccessClient) (*AppInstaller, error) {
func ProvideAppInstaller(
cfgProvider configprovider.ConfigProvider,
restConfigProvider apiserver.RestConfigProvider,
pluginStore pluginstore.Store,
pluginAssetsService *pluginassets.Service,
accessControlService accesscontrol.Service, accessClient authlib.AccessClient,
) (*AppInstaller, error) {
if err := registerAccessControlRoles(accessControlService); err != nil {
return nil, fmt.Errorf("registering access control roles: %w", err)
}
grafanaComAPIURL := os.Getenv("GRAFANA_COM_API_URL")
if grafanaComAPIURL == "" {
grafanaComAPIURL = "https://grafana.com/api/plugins"
}
coreProvider := meta.NewCoreProvider()
cloudProvider := meta.NewCatalogProvider(grafanaComAPIURL)
metaProviderManager := meta.NewProviderManager(coreProvider, cloudProvider)
localProvider := meta.NewLocalProvider(pluginStore, pluginAssetsService)
metaProviderManager := meta.NewProviderManager(localProvider)
authorizer := grafanaauthorizer.NewResourceAuthorizer(accessClient)
i, err := pluginsapp.ProvideAppInstaller(authorizer, metaProviderManager)
if err != nil {
@@ -44,6 +50,9 @@ func ProvideAppInstaller(accessControlService accesscontrol.Service, accessClien
}
return &AppInstaller{
metaManager: metaProviderManager,
cfgProvider: cfgProvider,
restConfigProvider: restConfigProvider,
PluginAppInstaller: i,
}, nil
}
+1 -1
View File
@@ -2,7 +2,6 @@ package appregistry
import (
"github.com/google/wire"
"github.com/grafana/grafana/pkg/registry/apps/quotas"
"github.com/grafana/grafana/pkg/registry/apps/alerting/historian"
"github.com/grafana/grafana/pkg/registry/apps/alerting/notifications"
@@ -14,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/registry/apps/logsdrilldown"
"github.com/grafana/grafana/pkg/registry/apps/playlist"
"github.com/grafana/grafana/pkg/registry/apps/plugins"
"github.com/grafana/grafana/pkg/registry/apps/quotas"
"github.com/grafana/grafana/pkg/registry/apps/shorturl"
)
+2 -2
View File
@@ -786,7 +786,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
if err != nil {
return nil, err
}
appInstaller, err := plugins.ProvideAppInstaller(acimplService, accessClient)
appInstaller, err := plugins.ProvideAppInstaller(configProvider, eventualRestConfigProvider, pluginstoreService, pluginassetsService, acimplService, accessClient)
if err != nil {
return nil, err
}
@@ -1447,7 +1447,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
if err != nil {
return nil, err
}
appInstaller, err := plugins.ProvideAppInstaller(acimplService, accessClient)
appInstaller, err := plugins.ProvideAppInstaller(configProvider, eventualRestConfigProvider, pluginstoreService, pluginassetsService, acimplService, accessClient)
if err != nil {
return nil, err
}
@@ -217,7 +217,6 @@ func (s *syncer) syncNamespace(ctx context.Context, namespace string, source ins
err := s.installRegistrar.Register(ctx, namespace, &install.PluginInstall{
ID: p.ID,
Version: p.Info.Version,
Class: install.Class(p.Class),
Source: source,
})
if err != nil {
@@ -17,6 +17,7 @@ type Plugin struct {
// App fields
Parent *ParentPlugin
Children []string
IncludedInAppID string
DefaultNavURL string
Pinned bool
@@ -85,6 +86,18 @@ func ToGrafanaDTO(p *plugins.Plugin) Plugin {
dto.Parent = &ParentPlugin{ID: p.Parent.ID}
}
if len(p.Children) > 0 {
children := make([]string, 0, len(p.Children))
for _, child := range p.Children {
if child != nil {
children = append(children, child.ID)
}
}
if len(children) > 0 {
dto.Children = children
}
}
return dto
}
+14 -14
View File
@@ -28,7 +28,7 @@ func TestIntegrationPluginMeta(t *testing.T) {
"apiVersion": "plugins.grafana.app/v0alpha1",
"kind": "Plugin",
"metadata": {"name": "%s"},
"spec": {"id": "grafana-piechart-panel", "version": "1.0.0"}
"spec": {"id": "piechart", "version": "1.0.0"}
}`, plugin1Name))
_, err := client.Resource.Create(ctx, plugin1, metav1.CreateOptions{})
require.NoError(t, err)
@@ -38,7 +38,7 @@ func TestIntegrationPluginMeta(t *testing.T) {
"apiVersion": "plugins.grafana.app/v0alpha1",
"kind": "Plugin",
"metadata": {"name": "%s"},
"spec": {"id": "grafana-clock-panel", "version": "1.0.0"}
"spec": {"id": "table", "version": "1.0.0"}
}`, plugin2Name))
_, err = client.Resource.Create(ctx, plugin2, metav1.CreateOptions{})
require.NoError(t, err)
@@ -57,14 +57,14 @@ func TestIntegrationPluginMeta(t *testing.T) {
foundIDs := make(map[string]bool)
for _, item := range response.Result.Items {
require.NotNil(t, item.Spec.PluginJSON)
foundIDs[item.Spec.PluginJSON.Id] = true
require.NotEmpty(t, item.Spec.PluginJSON.Id)
require.NotEmpty(t, item.Spec.PluginJSON.Type)
require.NotEmpty(t, item.Spec.PluginJSON.Name)
require.NotNil(t, item.Spec.PluginJson)
foundIDs[item.Spec.PluginJson.Id] = true
require.NotEmpty(t, item.Spec.PluginJson.Id)
require.NotEmpty(t, item.Spec.PluginJson.Type)
require.NotEmpty(t, item.Spec.PluginJson.Name)
}
require.True(t, foundIDs["grafana-piechart-panel"])
require.True(t, foundIDs["grafana-clock-panel"])
require.True(t, foundIDs["piechart"])
require.True(t, foundIDs["table"])
})
t.Run("list plugin metas with no plugins", func(t *testing.T) {
@@ -95,7 +95,7 @@ func TestIntegrationPluginMeta(t *testing.T) {
"apiVersion": "plugins.grafana.app/v0alpha1",
"kind": "Plugin",
"metadata": {"name": "%s"},
"spec": {"id": "grafana-piechart-panel", "version": "1.0.0"}
"spec": {"id": "piechart", "version": "1.0.0"}
}`, pluginName))
_, err := client.Resource.Create(ctx, plugin, metav1.CreateOptions{})
require.NoError(t, err)
@@ -109,10 +109,10 @@ func TestIntegrationPluginMeta(t *testing.T) {
}, &pluginsv0alpha1.Meta{})
require.NotNil(t, response.Result)
require.NotNil(t, response.Result.Spec.PluginJSON)
require.Equal(t, "grafana-piechart-panel", response.Result.Spec.PluginJSON.Id)
require.NotEmpty(t, response.Result.Spec.PluginJSON.Name)
require.NotEmpty(t, response.Result.Spec.PluginJSON.Type)
require.NotNil(t, response.Result.Spec.PluginJson)
require.Equal(t, "piechart", response.Result.Spec.PluginJson.Id)
require.NotEmpty(t, response.Result.Spec.PluginJson.Name)
require.NotEmpty(t, response.Result.Spec.PluginJson.Type)
})
t.Run("get plugin meta for non-existent plugin", func(t *testing.T) {