Plugin Extensions: Require meta-data to be defined in plugin.json during development mode (#93429)

* feat: add extensions to the backend plugin model

* feat: update the frontend plugin types

* feat(pluginContext): return a `null` if there is no context found

This will be necessary to understand if a certain hook is running inside a plugin context or not.

* feat: add utility functions for checking extension configs

* tests: fix failing tests due to the type updates

* feat(AddedComponentsRegistry): validate plugin meta-info

* feat(AddedLinksRegistry): validate  meta-info

* feat(ExposedComponentsRegistry): validate meta-info

* feat(usePluginComponent): add meta-info validation

* feat(usePluginComponents): add meta-info validation

* feat(usePluginLinks): add meta-info validation

* fix: only validate meta-info in registries if dev mode is enabled

* tests: add unit tests for the restrictions functionality

* tests: fix Go tests

* fix(tests): revert accidental changes

* fix: run goimports

* fix: api tests

* add nested app so that meta data can bested e2e tested

* refactor(types): extract the ExtensionInfo into a separate type

* refactor(extensions/utils): use Array.prototype.some() instead of .find()

* refactor(usePluginLinks): update warning message

* feat(usePluginExtensions()): validate plugin meta-info

* Wip

* fix(e2e): E2E tests for extensions

* fix(extensions): allow multiple "/" slashes in the extension point id

* fix(extensions/validators): stop validating the plugin id pattern

---------

Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
This commit is contained in:
Levente Balogh
2024-10-04 08:41:26 +02:00
committed by GitHub
co-authored by Erik Sundell
parent 7188c13d22
commit 6096f46774
53 changed files with 3197 additions and 243 deletions
+54
View File
@@ -98,6 +98,15 @@ func TestLoader_Load(t *testing.T) {
Dependencies: plugins.Dependencies{
GrafanaVersion: "*",
Plugins: []plugins.Dependency{},
Extensions: plugins.ExtensionsDependencies{
ExposedComponents: []string{},
},
},
Extensions: plugins.Extensions{
AddedLinks: []plugins.AddedLink{},
AddedComponents: []plugins.AddedComponent{},
ExposedComponents: []plugins.ExposedComponent{},
ExtensionPoints: []plugins.ExtensionPoint{},
},
Category: "cloud",
Annotations: true,
@@ -141,6 +150,15 @@ func TestLoader_Load(t *testing.T) {
Dependencies: plugins.Dependencies{
GrafanaVersion: "*",
Plugins: []plugins.Dependency{},
Extensions: plugins.ExtensionsDependencies{
ExposedComponents: []string{},
},
},
Extensions: plugins.Extensions{
AddedLinks: []plugins.AddedLink{},
AddedComponents: []plugins.AddedComponent{},
ExposedComponents: []plugins.ExposedComponent{},
ExtensionPoints: []plugins.ExtensionPoint{},
},
Executable: "test",
Backend: true,
@@ -195,6 +213,9 @@ func TestLoader_Load(t *testing.T) {
{Type: "datasource", ID: "graphite", Name: "Graphite", Version: "1.0.0"},
{Type: "panel", ID: "graph", Name: "Graph", Version: "1.0.0"},
},
Extensions: plugins.ExtensionsDependencies{
ExposedComponents: []string{},
},
},
Includes: []*plugins.Includes{
{
@@ -228,6 +249,12 @@ func TestLoader_Load(t *testing.T) {
Slug: "nginx-datasource",
},
},
Extensions: plugins.Extensions{
AddedLinks: []plugins.AddedLink{},
AddedComponents: []plugins.AddedComponent{},
ExposedComponents: []plugins.ExposedComponent{},
ExtensionPoints: []plugins.ExtensionPoint{},
},
},
Class: plugins.ClassExternal,
Module: "public/plugins/test-app/module.js",
@@ -266,6 +293,15 @@ func TestLoader_Load(t *testing.T) {
Dependencies: plugins.Dependencies{
GrafanaVersion: "*",
Plugins: []plugins.Dependency{},
Extensions: plugins.ExtensionsDependencies{
ExposedComponents: []string{},
},
},
Extensions: plugins.Extensions{
AddedLinks: []plugins.AddedLink{},
AddedComponents: []plugins.AddedComponent{},
ExposedComponents: []plugins.ExposedComponent{},
ExtensionPoints: []plugins.ExtensionPoint{},
},
Backend: true,
State: plugins.ReleaseStateAlpha,
@@ -312,6 +348,15 @@ func TestLoader_Load(t *testing.T) {
Dependencies: plugins.Dependencies{
GrafanaVersion: "*",
Plugins: []plugins.Dependency{},
Extensions: plugins.ExtensionsDependencies{
ExposedComponents: []string{},
},
},
Extensions: plugins.Extensions{
AddedLinks: []plugins.AddedLink{},
AddedComponents: []plugins.AddedComponent{},
ExposedComponents: []plugins.ExposedComponent{},
ExtensionPoints: []plugins.ExtensionPoint{},
},
Backend: true,
State: plugins.ReleaseStateAlpha,
@@ -393,11 +438,20 @@ func TestLoader_Load(t *testing.T) {
GrafanaDependency: ">=8.0.0",
GrafanaVersion: "*",
Plugins: []plugins.Dependency{},
Extensions: plugins.ExtensionsDependencies{
ExposedComponents: []string{},
},
},
Includes: []*plugins.Includes{
{Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: org.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-memory"},
{Name: "Root Page (react)", Type: "page", Role: org.RoleViewer, Action: plugins.ActionAppAccess, Path: "/a/my-simple-app", DefaultNav: true, AddToNav: true, Slug: "root-page-react"},
},
Extensions: plugins.Extensions{
AddedLinks: []plugins.AddedLink{},
AddedComponents: []plugins.AddedComponent{},
ExposedComponents: []plugins.ExposedComponent{},
ExtensionPoints: []plugins.ExtensionPoint{},
},
Backend: false,
},
DefaultNavURL: "/plugins/test-app/page/root-page-react",